useEffect不会在路由更改时更新状态

时间:2019-09-25 12:40:57

标签: javascript reactjs react-hooks gatsby

我正在寻找一种解决方案,用于注册路线更改并使用statesetState应用新的useEffect。更改路线后,下面的当前代码不会更新setState的功能。

例如,如果pathname/,{{1}中的location.pathname === '/'中的{{1} createContext中的}}已注册pathname,但是如果/setState isHome已注册true

在重新加载浏览器时,pathname /page-1的设置正确,但是在使用setState进行路由更改时,则没有正确设置。此外,请注意,我正在使用Gatsby,并且这样做是在导入false

CreateContext.js

onMount

如果我在state Link{ Link } from 'gatsby'得到export const GlobalProvider = ({ children, location }) => { const prevScrollY = useRef(0); const [state, setState] = useState({ isHome: location.pathname === '/', // other states }); const detectHome = () => { const homePath = location.pathname === '/'; if (!homePath) { setState(prevState => ({ ...prevState, isHome: false })); } if (homePath) { setState(prevState => ({ ...prevState, isHome: true })); } }; useEffect(() => { detectHome(); return () => { detectHome(); }; }, [state.isHome]); return ( <GlobalConsumer.Provider value={{ dataContext: state, }} > {children} </GlobalConsumer.Provider> ); }; ,则我得到的其他任何路径名console.log(state.isHome),但是,如果我改变路线,则当前{直到我滚动并pathname适用为止,{1}}状态将保持在先前状态。

注册/状态的目的是每页更改CSS。

更改路线时如何使用true更新状态。以前,我会使用false来完成此操作,并向isHome注册useEffect,但是,我的理解是,使用isHome钩子不再需要这样做。

3 个答案:

答案 0 :(得分:2)

您想要的效果是“当位置更改然后更新我的状态时”,此翻译为useEffect代码,如下所示:

  useEffect(() => {
    detectHome();
    return () => {
      detectHome();
    };
  }, [location]);

答案 1 :(得分:0)

如果您正在使用react-router,则可以在useEffect中订阅位置更改事件:

import {browserHistory} from 'react-router';

...
useEffect(() => {
  return browserHistory.listen(detectHome);
}, []);
...

这将为您的detectHome函数预订安装时的位置更改,并在卸载时取消预订。

答案 2 :(得分:0)

我认为,如果您使用GlobalProvider作为根组件,在这种情况下,除非某些更改状态或道具,否则它只会渲染一次。所以有一些解释:

  useEffect(() => {
    detectHome();
    return () => {
      detectHome();
    };
  }, [state.isHome]);

上面的代码,state仅由此useEffect更新,因此它仅在第一次渲染后一次更新状态,并且detectHome返回{{1 }}仅在发生其他更新或useEffect首次不同时执行。对此解释有点困惑,但这就是。

但是解决方案是使用window的'popstate'事件:

state.isHome

我认为Gatsby应该操纵历史记录,因此将触发export const GlobalProvider = ({ children, location }) => { const prevScrollY = useRef(0); const [state, setState] = useState({ isHome: location.pathname === '/', // other states }); const detectHome = () => { const homePath = location.pathname === '/'; if (!homePath) { setState(prevState => ({ ...prevState, isHome: false })); } if (homePath) { setState(prevState => ({ ...prevState, isHome: true })); } }; useEffect(() => { window.addEventListener('popstate', detectHome) return () => { window.removeEventListener('popstate', detectHome) }; }, [state.isHome]); return ( <GlobalConsumer.Provider value={{ dataContext: state, }} > {children} </GlobalConsumer.Provider> ); }; 浏览器,并且您可以检测到网址的更改。