【问题标题】:How can I set a global context in Next.js without getting a "Text content did not match" error?如何在 Next.js 中设置全局上下文而不会出现“文本内容不匹配”错误?
【发布时间】:2020-09-19 02:51:30
【问题描述】:

我有一个 next.js 应用程序,它需要将 SESSION 数据拉入全局上下文。目前我有:

// _app.js

const App = ({ Component, pageProps }) => {

const start = typeof window !== 'undefined' ? window.sessionStorage.getItem('start') : 0;

  return (
    <ElapsedContext.Provider value={start}>
      <Component {...pageProps} />
    </ElapsedContext.Provider>
  )
};

export default App;

我正在像这样使用我的组件:

function MyComponent(props) {
  const start = useContext(ElapsedContext);
  return (
    // something using start;
  );
}

但是,当我在组件中使用该上下文时,组件会按预期呈现在页面上,但我得到 Warning: Text content did not match. Server: "0" Client: "5.883333333333345"

我认为是因为它最初传递 0,然后在窗口加载后从 SESSION 存储中提取数字。

  1. 如何解决此警告?
  2. 我可以放心地忽略此警告吗?

我已经尝试在 _app.js 文件中使用useEffect(在加载窗口后触发),但是初始状态对于我的组件来说不可用于构建它在初始渲染上构建它需要的东西......

【问题讨论】:

    标签: reactjs next.js react-context


    【解决方案1】:

    Next.js 在构建时呈现页面,或者由服务器呈现页面,这意味着 window 和因此 sessionStorage 不可用,因为它在 Node.js 环境中运行。

    如果您忽略此警告,React 将在页面加载后执行重新渲染。服务器渲染 React 的好处在于,当页面加载时,React 不必执行重新渲染,所以当这个警告出现时,你想避免它。

    虽然,由于 sessionStorage 在页面在浏览器中呈现之前不可用,因此您必须等到那时填充您的上下文。

    因此,为您的情况避免此错误的一种方法是执行以下操作:

    // context.js
    export const ElapsedContext = React.createContext(0);
    
    export const ElapsedProvider = ({ children }) => {
      const [state, setState] = React.useState(0);
    
      React.useEffect(() => {
        // on client side mount, set starting value
        setState(window.sessionStorage.getItem('start'))
      }, [])
    
      return (
        <ElapsedContext.Provider
          value={state}
        >
          {children}
        </ElapsedContext.Provider>
      );
    };
    
    
    // pages/_app.js
    export default function MyApp({ Component, pageProps }) {
      return <ElapsedProvider><Component {...pageProps} /></ElapsedProvider>
    }
    
    // pages/index.js
    export default function MyPage() {
      const start = React.useContext(ElapsedContext);
      if (start === 0) {
        return <Loading />
      }
    
      return <MyComponentThatUsesElapsed />
    }
    

    【讨论】:

      猜你喜欢
      • 2022-12-05
      • 2022-11-30
      • 2012-03-26
      • 2022-08-22
      • 2020-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多