在依赖 URL 的上下文中创建初始状态,window 未在 NextJS 中定义

creating initial state in context that depends on URL, window is not defined in NextJS

我正在尝试检测我的 nextjs 应用程序中的 URL 路径,并根据 context 中的 url 路径设置初始状态,但我得到 window 没有定义。我知道 window 在客户端呈现之前不会被定义,但是如果我想将初始状态传递到上下文中,我应该把它放在哪里?

import React, {createContext, useReducer} from "react";
import Reducer from './reducer'

const initialState = {
  'about': window.location.pathname == 'about' ? true : false
};

const Store = ({children}) => {

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


    return (
        <Context.Provider value={[state, dispatch]}>
            {children}
        </Context.Provider>
    )
};

export const Context = createContext(initialState);
export default Store;

useReducer 有能力做 lazy initialization via a third argument. Perhaps you can dispatch an action in your component when window is available such as in 或在 useEffect():

中使用钩子
// set initial state, can also pass values here from dispatch also
// This would be called when `window` is available
function init() {
 return {
   'about': window.location.pathname == 'about' ? true : false
 };
}

// ...
// Some initial state
const initialState = { about: false };

// ..

useReducer(Reducer, initialState, init); // pass third argument, the init function

然后更新你的 reducer 以使用 init:

function reducer(state, action) {
  switch (action.type) {
    // ...
    case 'init':
      return init(); // execute init function
  }
}

最后使用类似 useEffect 挂钩的东西从您的组件触发这个新的动作类型:

// Assuming you are using context to get store state/dispatch
const [state, dispatch] = useContext(MyContext);
useEffect(() => {
  dispatch({ type: 'init' }); // could pass window values here also via payload perhaps
}, []);

希望对您有所帮助!

您可以访问 RouterContext,您可以使用它提供的 pathname 值。

import { useRouter } from 'next/router';

const Store = ({children}) => {
  const router = useRouter();

  const [state, dispatch] = useReducer(Reducer, {
      about: router.pathname === '/about'
  });

  // rest of the logic

}