ReactJS为什么useEffect有时在每个安装/渲染上运行,而不是仅在第一个上运行

时间:2019-05-17 21:43:27

标签: reactjs react-redux react-router-v4 use-effect react-localize-redux

我在App.js的路由中有一个useEffect

    <Switch>
      <Route exact path={['/en', '/fr']} component={HomePage} />
      <Route path={['/en/*', '/fr/*']}>
        <Route path="/:lang/*" component={DefaultLanguage} />

在同一文件(App.js)中,我们具有这样的组件(使用react-localize-redux):

const DefaultLanguage = withLocalize(
  ({ activeLanguage, setActiveLanguage, ...props }) => {
    useEffect(() => {
      console.log('setting active language');
      setActiveLanguage(props.match.params.lang);
    }, []);
    return <></>;
  }
);

问题是我单击的每个链接都运行setActiveLanguage,即使我将[]设置为仅在首次渲染时运行(因为这是我唯一一次关注从URL设置语言的时间),我遇到了这个问题应用程序的其他部分。以我的理解,除非依赖关系发生变化,否则不应在每次安装组件时都运行useEffect,但似乎我缺少一个细节。

1 个答案:

答案 0 :(得分:1)

您是正确的,将空数组传递给useEffect会阻止它在后续的 renders 上运行,但是如果卸载了组件然后再次进行了安装,那不会阻止它运行

我的猜测是,通过单击链接,您实际上是在卸载然后重新安装DefaultLanguage组件。

您可以通过从useEffect钩子返回清除函数来进行测试。

例如

useEffect(() => {
      console.log('setting active language');
      setActiveLanguage(props.match.params.lang);

      return () => console.log('Unmounting');
    }, []);

如果您看到该日志,则说明您已找到问题。

一种快速而肮脏的解决方案是检查并查看语言是否已更改,如果已更改,请进行设置。那不会解决潜在的不必要的挂载/卸载,但至少会避免再次设置语言。

useEffect(() => {
      if (activeLanguage !== props.match.params.lang) {
        console.log('setting active language');
        setActiveLanguage(props.match.params.lang);
      }
    }, []);