客户端组件,nextjs13中的localstorage

vbp*_*wrr 3 server-side-rendering next.js

我正在将项目从 React 转移到 nextjs 并遇到问题。我有一个处理登录上下文并使用本地存储的全局包装器。我在顶部设置了“use client”指令,但该组件也尝试在服务器上呈现,并且此代码给出了水合错误:

export function AuthProvider(props) {
  
  const initialParsedToken =  typeof localStorage !== 'undefined' ? localStorage.getItem("jwt") : null

  if (initialParsedToken) {
    const decodedToken = jwtDecode<JwtInterface>(initialParsedToken);

    if (decodedToken.exp * 1000 < Date.now()) {
      localStorage.removeItem("token");
    } else {
      initialState.user = decodedToken;
    }
  }

  const [state, dispatch] = useReducer(authReducer, initialState);

  if (typeof localStorage === 'undefined'){
    return null
  }

  const login = (userData: any) => {
    localStorage.setItem("jwt", userData.token);
    dispatch({ type: "LOGIN", payload: userData });
  };

  function logout() {
    localStorage.removeItem("jwt");
    dispatch({ type: "LOGOUT" });
  }

  return (
      <AuthContext.Provider
          value={{ user: state.user, login, logout }}
          {...props}
      />
  );
}

Run Code Online (Sandbox Code Playgroud)

错误:

    Hydration failed because the initial UI does not match what was rendered on the server.
Run Code Online (Sandbox Code Playgroud)

接下来如何使用useReducer挂钩,或者使身份验证逻辑与此框架一起使用?

我计划将静态内容渲染为服务器组件,并具有客户端部分,但是我可以避免在每个客户端组件中使用丑陋的 useffect hack,而只在嵌套的动态内容中添加一个use 客户端吗?

我尝试在父组件中使用 useffect hack,但嵌套组件仍然不起作用。

小智 5

您应该检查窗口的类型,以确保您位于客户端

if (typeof window !== undefined){
....your local storage logic
}
Run Code Online (Sandbox Code Playgroud)

另外,您应该考虑将令牌移动到 cookie 而不是本地存储,因为它不会导致冲突,并且您可以使用 context 参数在服务器端检查您的 cookie,请参阅