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



我正在寻找一种解决方案来注册路由更改并使用setStateuseEffect应用新state。下面的当前代码不会在更改路由时更新setState的功能。

例如,我在createContext内向location.pathname === '/'注册/pathname,如果pathname/isHomesetStatetrue注册,但是如果pathname/page-1setState注册false

在浏览器重新加载时,onMount正确设置了state,但是在使用Link更改路由时,这不会。另外,请注意,我正在使用盖茨比,并在这样做时导入{ Link } from 'gatsby'

创建上下文.js

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/我得到true,我得到的任何其他路径名false,但是,如果我更改路由,当前isHome状态将保持先前状态,直到我滚动并useEffect适用。

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

更改路线时如何使用useEffect更新状态。以前,我会用componentDidUpdate来做到这一点,并针对props.location.pathname注册prevProps.location.pathname,但是,我的理解是,对于useEffect钩子,这不再是必需的。

你想要的效果是"当位置更改然后更新我的状态时",这是useEffect代码翻译的,如下所示:

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

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

import {browserHistory} from 'react-router';
...
useEffect(() => {
return browserHistory.listen(detectHome);
}, []);
...

这将订阅您的detectHome函数,以便在装载时更改位置,并在卸载时取消订阅。

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

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

上面的这段代码,state只由这个useEffect更新,所以它只在第一次渲染后更新一次状态,而 return 的detectHomeuseEffect只有在发生其他更新或state.isHome与第一次不同时才执行。这个解释有点令人困惑,但就是这样。

但是对于解决方案,请使用窗口的"popstate"事件:

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>
);
};

我认为盖茨比应该操纵历史记录,所以这将触发浏览器popstate,您可以检测到 url 的更改。

相关内容

  • 没有找到相关文章

最新更新