React useEffect 清理函数中的依赖项未更新

时间:2021-06-02 09:39:21

标签: reactjs use-effect usecallback

当我尝试使用 useEffect 在组件卸载时调用清理函数时遇到一个奇怪的问题。

在我的 useEffect 返回中,我调用了一个 useCallback 函数,其中正确添加了依赖项。在那里检查名为 status 的状态变量,但此变量从未从初始状态更新。我无法将变量传递给 useEffect,因为我只想在组件因特定原因卸载时触发它。 我在 codepen here 中重新创建了一个简化版本,但我无法理解这一点。也许有人知道为什么会这样? 谢谢! (这是最近才开始发生的,之前它可以正常工作,所以我更加困惑!)

3 个答案:

答案 0 :(得分:1)

感谢您的回答。 所以,我终于知道发生了什么。 useEffect 创建一个闭包并且函数在该闭包中,这意味着作为字符串的状态保持为第一次渲染(当闭包被创建时)并且它永远不会更新。 正如@ilkerkaran 所提到的那样,一种方法是使用 useRef,但那是因为它创建了一个对象,这意味着 ref.current 属性具有指向原始属性的链接,并且始终保持同步。 另一种方法是使用 useMemo 并返回一个带有 status 属性的对象,实际上它实际上是 useRef 。 因此,实际上,如果状态是一个对象并且我们将状态作为依赖项传递,那么出于同样的原因,stayus 属性将按预期工作。我希望这对其他人也有帮助并节省一些时间

答案 1 :(得分:0)

实际上,您的代码不会发生这种情况。回调函数根据依赖数组更新。您可以通过在 useEffect 上方调用 remove() 来看到这一点。这样,func 将在每次渲染时执行。

在你的例子中会发生什么;

  • 它呈现,(通过第一次按下切换按钮)
  • 然后通过在 useEffect 中调用 setStatus("mounted") 来触发第二次渲染(通过第二次按下切换按钮)
  • 然后它为 te 最后一次呈现卸载 使用默认状态值

最后一部分实际上也困扰着我。您可以通过在 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])