React useEffect 清理函数中的依赖没有更新
Posted
技术标签:
【中文标题】React useEffect 清理函数中的依赖没有更新【英文标题】:Dependencies in React useEffect cleanup function are not updated 【发布时间】:2021-08-20 11:09:04 【问题描述】:我在尝试使用 useEffect 在卸载组件时调用清理函数时遇到了一个奇怪的问题。
在我的 useEffect 返回中,我调用了一个 useCallback 函数,其中正确添加了依赖项。在那里检查名为status
的状态变量,但该变量永远不会从初始状态更新。我无法将变量传递给 useEffect,因为我只想在组件因特定原因卸载时触发它。
我在 codepen here 中重新创建了一个简化版本,但我无法理解这一点。也许有人知道为什么会这样?
谢谢!
(这只是最近才开始发生的,它以前工作过,所以我更加困惑!)
【问题讨论】:
【参考方案1】:感谢您的回答。 所以,我终于知道发生了什么。 useEffect 创建一个闭包,并且函数在该闭包中,这意味着作为字符串的状态与第一次渲染一样(创建闭包时)保持不变,并且永远不会更新。 正如@ilkerkaran 所提到的,一种方法是使用useRef,但这是因为它创建了一个对象,这意味着 ref.current 属性具有到原始对象的链接并且它始终保持同步。 另一种方法是执行 useMemo 并返回一个具有 status 属性的对象,这实际上是 useRef 在引擎盖下。 所以实际上,如果 state 是一个对象,并且我们将 state 作为依赖项传递,则 stayus 属性将出于同样的原因按预期工作。我希望这对其他人也有帮助并节省一些时间
【讨论】:
谢谢。 useRef 是迄今为止我见过的最好的解决方案。【参考方案2】:实际上,您的代码并非如此。回调函数根据依赖数组更新。您可以通过在 useEffect 上方调用 remove()
来看到这一点。这样,函数将在每次渲染时执行。
在您的示例中发生了什么;
它呈现,(通过第一次按下切换按钮) 然后在 useEffect 中调用setStatus("mounted")
触发第二次渲染(通过第二次按下切换按钮)
然后它会在上次卸载时渲染 默认状态值
最后一部分实际上也让我感到烦恼。您可以通过在 useEffect 定义上方放置一个简单的 console.log 来观察此行为。
您也可以通过使用 useRef
而不是 useState 来解决此问题
【讨论】:
【参考方案3】:原因是你的useEffect
。
React.useEffect(() =>
setStatus("mounted")
return () => remove()
, [])
你有一个 useEffect 的依赖项设置为 []。这意味着您的 useEffect 将只运行一次。因此,这就是您的组件从上到下执行流程的方式,因此您创建了一个删除函数,此时您的初始状态为 not mounted
。现在你的dom被画了。你 useEffect 被调用你设置状态现在你得到一个全新的删除功能。现在您卸载组件,清理将使用 第一次渲染中的 remove
函数。
为了让您的状态反映在 remove
中,您需要在 useEffect
中添加 status
作为依赖项。
React.useEffect(() =>
setStatus("mounted")
return () => remove()
, [status])
【讨论】:
以上是关于React useEffect 清理函数中的依赖没有更新的主要内容,如果未能解决你的问题,请参考以下文章
react 钩子中的 useEffect 执行顺序及其内部清理逻辑是啥?
React+Typescript:修复 UseEffect Hook(回调+清理函数错误)
socket.io useEffect 清理函数 react
如何取消 useEffect 清理函数中的所有订阅和异步任务?