如何消除在 Next.js 中使用 React context 的延迟?

问题描述 投票:0回答:1

我试图在反应上下文中存储一些有关客户端的基本(非敏感)用户信息,例如他们的显示名称和个人资料图片。该信息存储在本地存储中,以便即使客户端关闭/重新加载页面,它也会持续存在,并且上下文从那里获取数据,并将其显示在客户端组件中。从功能上来说,它工作得很好。但是,我遇到了一些问题:

  1. 为了避免水合不匹配错误,我必须禁用整个组件的 SSR。

  2. 即使我保持启用 SSR,即使我构建了应用程序,内容也比其他客户端组件需要更多的时间来完成。这种布局转变真的很困扰我。

我的问题是,如何才能让这些信息立即显示出来?我还没有看到其他人遇到这个问题。如果我存储的方式错误,正确的方式是什么?

我已经创建了该错误的“最小工作示例”。我尝试查找在 nextjs 中使用 React context 的各种方法,但它们似乎都表明我做错了什么。我还尝试对 next-themes 进行逆向工程以弄清楚它是如何工作的,但我不太理解它。 任何帮助将不胜感激!

reactjs typescript next.js local-storage react-context
1个回答
0
投票
AuthContext

组件及其与 Next.js 中服务器端渲染的交互。

问题的出现是因为服务器和客户端之间的

userData

值不同,导致水合失败。发生此失败的原因是 React API

hydrateRoot()
希望渲染的内容与服务器渲染的 HTML 相匹配。
您可以参考

React文档

和中间的“陷阱”部分了解更多细节。建议避免在渲染逻辑中直接使用 typeof window !== 'undefined' 等检查或访问

localStorage
等仅限浏览器的 API,因为这可能会导致服务器和客户端快照之间不匹配。
这是我的解决方法:

使用默认值
    useState
  1. 初始化
    null
    钩子,以确保初始渲染一致。
    组件安装后,使用 
  2. useEffect
  3. 钩子更新
    userData
    删除动态导入并直接导入
  4. ClientComponent
  5. 更新前在 clientComponent 中显示一些内容
  6. 这是修改后的
AuthContext

组件:

import React, { createContext, useContext, useEffect, useState, Dispatch, SetStateAction } from "react";

export default function AuthContext({
  children,
}: {
  children: React.ReactNode;
}) {
  const [user, setUser] = useState<string | null>(null); // Initialize with null
  
  // update after component mount
  useEffect(() => {
    const userData = getUser();
    if(userData){
      setUser(userData);
    }
  }, []);

  return (
    <Context.Provider value={{ userData: user, setUserData: setUser }}>
      {children}
    </Context.Provider>
  );
}

export const useAuthContext = () => useContext(Context);

const getUser = () => {
  if(typeof window === 'undefined') return null; // Check for server-side rendering
  let user;
  try {
    user = localStorage.getItem("user");
    if (!user) {
      user = "I want this to be rendered instantly too!";
      localStorage.setItem("user", user);
      return user;
    }
  } catch (e) {}
  return user;
};

请注意,这种方法可能会使水合速度变慢,因为您的组件必须渲染两次。干扰慢速连接的用户体验。 JavaScript 代码的加载可能会比初始 HTML 渲染晚得多,因此在水合后立即渲染不同的 UI 也可能会让用户感到不舒服。

但是,您不应该在渲染逻辑中访问仅限浏览器的 API。 希望这对您有用。

© www.soinside.com 2019 - 2024. All rights reserved.