当我尝试使用 useEffect 在组件卸载时调用清理函数时遇到一个奇怪的问题。
在我的 useEffect 返回中,我调用了一个 useCallback 函数,其中正确添加了依赖项。在那里检查名为 status
的状态变量,但此变量从未从初始状态更新。我无法将变量传递给 useEffect,因为我只想在组件因特定原因卸载时触发它。
我在 codepen here 中重新创建了一个简化版本,但我无法理解这一点。也许有人知道为什么会这样?
谢谢!
(这是最近才开始发生的,之前它可以正常工作,所以我更加困惑!)
答案 0 :(得分:1)
感谢您的回答。 所以,我终于知道发生了什么。 useEffect 创建一个闭包并且函数在该闭包中,这意味着作为字符串的状态保持为第一次渲染(当闭包被创建时)并且它永远不会更新。 正如@ilkerkaran 所提到的那样,一种方法是使用 useRef,但那是因为它创建了一个对象,这意味着 ref.current 属性具有指向原始属性的链接,并且始终保持同步。 另一种方法是使用 useMemo 并返回一个带有 status 属性的对象,实际上它实际上是 useRef 。 因此,实际上,如果状态是一个对象并且我们将状态作为依赖项传递,那么出于同样的原因,stayus 属性将按预期工作。我希望这对其他人也有帮助并节省一些时间
答案 1 :(得分:0)
实际上,您的代码不会发生这种情况。回调函数根据依赖数组更新。您可以通过在 useEffect 上方调用 remove()
来看到这一点。这样,func 将在每次渲染时执行。
在你的例子中会发生什么;
setStatus("mounted")
来触发第二次渲染(通过第二次按下切换按钮)最后一部分实际上也困扰着我。您可以通过在 useEffect 定义上方放置一个简单的 console.log 来观察这种行为。
您也可以通过使用 useRef
而不是 useState 来解决此问题
答案 2 :(得分:0)
这是因为您的 useEffect
.
React.useEffect(() => {
setStatus("mounted")
return () => remove()
}, [])
您有一个 useEffect 的依赖项设置为 []。这意味着您的 useEffect 将只运行一次。所以这就是流程如何从上到下执行您的组件,因此您创建了一个 remove 函数,此时您的初始状态为 not mounted
。现在你的 dom 被画了。你 useEffect 被调用,你设置了状态,现在你得到了一个全新的 remove 函数。现在您卸载组件,清理工作将使用 第一次渲染 中的 remove
函数。
为了让您的状态反映在 remove
中,您需要在 status
中添加 useEffect
作为依赖项。
React.useEffect(() => {
setStatus("mounted")
return () => remove()
}, [status])