繁体   English   中英

每次渲染时都将不同的 function 传递给 useEffect? - ReactJS 使用效果

[英]Different function gets passed to useEffect on every render? - ReactJS useEffect

我正在浏览 reactjs 文档中的useEffect ,我在这里找到了这个声明

经验丰富的 JavaScript 开发人员可能会注意到,传递给 useEffect 的 function 在每次渲染时都会有所不同。

我们将 function 传递给 useEffect ,据说这个 function 对于每个渲染都是不同的。 useEffect 可以访问 state 和道具,因为它位于 function 组件内,当其中任何一个更改时,我们可以看到 ZC1C425268E68385D1AB5074C17A94F14E 的更改。 这不清楚,因为在下一行文档中

这是故意的。 事实上,这让我们可以从效果内部读取计数值,而不必担心它会过时。

为了解决这个问题,假设我们有一个 function

function foo(n) {
    bar = () => {
        setTimeout(() => console.log({n}), 50);
        return n;
    }
    setTimeout(() => {n = 10}, 0);
    setTimeout(() => {n = 20}, 100);
    setTimeout(() => {n = 30}, 150);
    return bar;
}

baz = foo(1);
baz(); //prints 10
setTimeout(baz, 300); //prints 30

似乎当闭包值(n)发生变化时,我们可以看到 setTimeout 的回调发生了变化(并且这个回调不会随着时间而改变)。 那么,useEffect 的 function 中的封闭值(状态/道具)如何变得过时,如文档中所述?

我在这里错过了什么吗? 我认为与 React 相比,它更像是一个 JS 问题,所以我举了一个 JS 示例。

几天前我找到了答案,正如上面评论中提到的@apokryfos (再次感谢你)。 程序执行过程现在变得更有意义了。 我想在这里总结一下我的学习。

首先,我考虑的代码与React doc 语句的比较(用@apokryfos的话)不同,这是真的。 In case of static HTML + vanilla JS where the HTML button has an event-listener JS function, this function is declared only once and when the event occurs the same JS function is executed everytime.

我在问题中给出的代码与此类似,因此在控制台或事件侦听器中执行时只会声明一次。

React (或任何基于 state 的 UI 库/框架)的情况下,HTML 不是 static,它需要在状态更改时更改 在执行方面(考虑React ),当我们调用它时(在JSX中)将创建组件,并且组件的函数/类将完全从上到下执行。 这表示

  • 从所有不处理state的事件处理程序、常量到useState 的被破坏元素useEffect的回调函数,一切都重新初始化。

  • 如果父级的 state 更改启动其子级的渲染(在正常情况下),则子级将需要使用新道具和/或新 state 完全重新渲染自己以显示更新的 UI

  • 考虑 React 文档(链接)中的示例,在每次渲染后都会执行没有依赖关系的useEffect ,这里它通过显示当前的 state 值来更新 DOM。 除非回调 function 具有该 state 的最新值,否则它只会打印陈旧值。 所以在这里重新初始化函数是回调函数中没有陈旧值的主要原因

     function Example() { const [count, setCount] = useState(0); useEffect(() => { document.title = 'You clicked ${count} times'; }); }

这有时是一种恩惠,也是一种诅咒。 假设如果我们将 useState 的setState function发送给孩子,并且在孩子中,我们有一个useEffect (进行网络调用以获取数据),它将这个 function 作为其依赖项。 现在,对于父项中的每个 state 更改,即使是否存在用例,useEffect 也会被触发,因为此 function 依赖项发生更改(因为每次更新都会重新初始化函数)。 为了避免这种情况,我们可以在我们想要记住的函数上使用useCallback ,并且仅在某些参数发生更改时才更改,但不建议在useEffect的回调 function 上使用它,因为我们可能会以陈旧的值结束。

延伸阅读:

  1. GeeksForGeeks 使用回调
  2. useEffect的源码解释
  3. useEffect的另一种SourceCode解释

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM