我正在寻找一种解决方案,用于注册路线更改并使用state
和setState
应用新的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
钩子不再需要这样做。
答案 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>
);
};
浏览器,并且您可以检测到网址的更改。