создание начального состояния в контексте, который зависит от URL, окно не определено в NextJS - PullRequest
0 голосов
/ 20 июня 2020

Я пытаюсь определить путь URL-адреса в моем следующем js приложении и установить начальное состояние на основе пути URL-адреса в context, но окно получения не определено. Я знаю, что 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;

Ответы [ 2 ]

1 голос
/ 20 июня 2020

У вас есть доступ к 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

}
0 голосов
/ 20 июня 2020

useReducer имеет возможность выполнять ленивую инициализацию через третий аргумент. Возможно, вы можете отправить действие в своем компоненте, когда доступно окно, например, в componentDidMount () или с хуками внутри 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

Затем обновите свой редуктор, чтобы использовать 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
}, []);

Надеюсь, это поможет!

...