【问题标题】:useEffect run once for every component instanceuseEffect 为每个组件实例运行一次
【发布时间】:2021-05-20 00:59:58
【问题描述】:

我一直使用useEffect()[] 作为我想运行一次的代码的参数。但是在已经构建了许多项目之后,我发现如果它在某处呈现组件的一个实例时运行一次,它根本不会在其他任何地方运行。这意味着如果您在其他地方重用该组件,即使它们是第一次渲染,它也不会在其中运行。

父组件

  const [bl, setBl] = useState(true);
  return (
    <div className="App">
      <button onClick={(e) => setBl(!bl)}>Click</button>
      {bl ? <Comp page="page1" /> : <Comp page="page2" />}
    </div>
  );

子组件

function Comp({ page }) {
  useEffect(() => {
    console.log(page);
  }, []);

  return (
    <div>
      <h1>Component at {page}</h1>
    </div>
  );
}

这里只记录“page1”,不记录其他组件的任何内容,即page2

为了在每个实例中记录一次页面名称,我现在在使用效果之前添加var rnd = Math.random();这一行,并添加[rnd]作为参数,以便它在每个实例中运行一次。

所以我的问题是,有没有更好的方法来做到这一点?意味着在每个实例中运行一次,比像我使用的那样依赖随机机会更好?

我可以在这里使用[page],但是如果这里没有任何独特的道具呢?

您可以检查代码框here

【问题讨论】:

  • 您的开头段落似乎自相矛盾,如果每个实例运行一次,那么它肯定在每个实例中运行吗?您是否尝试过在没有条件的情况下包含多个实例?
  • @DBS 语言歧义,我编辑了,谢谢。
  • 您可以使用单个组件实现相同的效果:&lt;Comp {...(bl ? {page:"page1"} : {page:"page2"})} /&gt;

标签: reactjs react-hooks use-effect


【解决方案1】:

问题在于,对于 React,将 &lt;Comp page="page1" /&gt; 替换为 &lt;Comp page="page2" /&gt; 无法与简单地更新现有组件中的 prop 值区分开来。

因此,当 bl 更改时,React 不会卸载旧的 Comp 并安装另一个 - 它只会更新现有组件,并且仅当它们的依赖关系发生更改时才会触发效果。在你的情况下,依赖列表是空的,所以效果只运行一次 - 在挂载时。

为了实现你想要的,你可以尝试在状态改变时强制重新挂载,即让 React 看到 Comp 的两个实例是独立的。为此,您可以使用特殊的 key 属性 - 它通常用于元素列表,但这里也可以使用:

  const [bl, setBl] = useState(true);
  return (
    <div className="App">
      <button onClick={(e) => setBl(!bl)}>Click</button>
      {bl ? <Comp key="page1" page="page1" /> : <Comp key="page2" page="page2" />}
    </div>
  );

【讨论】:

    【解决方案2】:

    我发现如果它在某处呈现组件的一个实例时运行一次,它根本不会在其他任何地方运行

    完全没有:)

    UseEffect 触发每个组件安装。但如果您的依赖项数组为空,则不用于更新!

    你的情况在这里,React 只更新同一组件上的 page 道具,所以它不会触发你的 useEffect

    您有 2 个解决方案:

    • 要么将您的 page 属性添加到您的 useEffect 依赖数组中(所以每次 page 更改时,您的 useEffect 都会被触发)
    • key 添加到您的组件中,具体取决于您的 if/else。对于 React,如果它是“相同”的组件,但在 2 个渲染中使用不同的键,React 将卸载第一个,并安装第二个(因此您的 useEffect 将被触发)

    【讨论】:

      【解决方案3】:

      尝试将依赖变量放入useEffect的依赖列表中:

      function Comp({ page }) {
        useEffect(() => {
          console.log(page);
        }, [page]);
      
        return (
          <div>
            <h1>Component at {page}</h1>
          </div>
        );
      }
      

      【讨论】:

      • 谢谢。我会那样做。但是如果组件没有任何独特的道具怎么办
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-23
      • 1970-01-01
      • 2018-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-13
      相关资源
      最近更新 更多