如何在React的useEffect钩子中在不同的调用之间获取竞态条件标志?

huangapple go评论174阅读模式
英文:

How do a fetch race condition flag in React's useEffect hook between different calls?

问题

这个问题可能是一个简单的问题,但我在我的搜索中没有找到任何东西。不同的useEffect钩子调用如何共享在fetch竞争条件标志中的值?

我的意思是,在这个链接中:使用useEffect钩子获取数据的竞争条件,作者使用一个名为active的标志来控制获取数据的竞争条件。我想知道useEffect钩子的前一个(或下一个)调用如何访问来自清理函数的返回值false(这个值是如何共享的?),以及它是如何在JavaScript调用堆栈中工作的。

英文:

This question might be a simple question, but I found nothing in here in my searches. How do different useEffect hook calls share the value in a fetch race condition flag?

What I meant is that, in this link: race condintions in fetching data with useEffect hook, the author uses a flag active to control race condition on fetches. I want to know how the previous (or next) call of the useEffect hook gets access to the returned value false from the clean up function (how is the value shared?). And how does it work in the javascript callstack.

答案1

得分: 0

上一个(或下一个)useEffect钩子的调用如何访问清理函数返回的值?这个值是如何共享的?

根本不共享。每个effect执行都有自己的active值 - 它只在异步的fetchData函数和返回的清理函数之间共享,它们都是在相同作用域下的闭包。

只是React在运行组件状态改变时,会在再次运行effect之前清理上一次渲染的effect。它会记住返回的清理函数(如果有的话),只要effect还在运行,就会在effect结束时调用它。

英文:

> How does the previous (or next) call of the useEffect hook get access to the returned value from the clean up function? How is the value shared?

It is not shared at all. Every effect execution has its own active value - it is only shared between the asynchronous fetchData function and the returned cleanup function, they are both closures over the same scope.

It's just that react cleans up the effect from the last render before running the effect again when the component state changes. It remembers the returned cleanup function (if any) while the effect is active, and calls it when the effect should end.

答案2

得分: 0

我也对这篇帖子感到非常困惑。作用域方面没有什么神奇的事情,每个清理函数只能访问其作用域内定义的 active 实例。关键细节在于,尽管 useEffect 函数调用会进行长时间的 API 请求,但函数本身几乎立即返回一个待处理的承诺(promise)。因此,当你第二次点击获取按钮时,第一个请求的清理函数会立即运行,并将请求1的 active 设置为 false

使用提供的 CodeSandbox 的示例时间线:

  1. 点击获取按钮1。
  2. useEffect 函数运行:active1 = true,API request1 发送。
  3. 待处理request1 承诺立即返回。request1 尚未 完成。
  4. 点击获取按钮2。
  5. 在再次运行 useEffect 函数之前,按钮1的清理函数运行(即使 request1 尚未完成!):active1 = false
  6. useEffect 函数再次运行:active2 = true,API request2 发送。
  7. request1 最终完成,但其结果被忽略,因为在步骤5中将 active1 设置为了 false。
  8. request2 最终完成,其结果被使用,因为 active2 仍然为 true。

使用 CodeSandbox 的分支版本,其中添加了 console.log 帮助我搞清楚情况。

英文:

I was very confused by this post as well. There's nothing magical going on with scopes, each clean up function only has access to the instance of active defined within its scope. The key detail is that although the useEffect function call has a long running API request, the function itself returns almost immediately with a pending promise. Therefore, when you click the fetch button a second time, the clean up function for the first request runs immediately, and set request 1's active to false.

Example timeline using the provided CodeSandbox:

  1. Fetch button press 1.
  2. useEffect function runs: active1 = true, API request1 sent.
  3. Pending promise for request1 returned immediately. request1 has not completed.
  4. Fetch button press 2.
  5. Before useEffect function runs again, button press 1 clean up runs (even though request1 hasn't finished yet!): active1 = false.
  6. useEffect function runs again: active2 = true, API request2 sent.
  7. request1 finally completes, but its results are ignored because active1 was set to false in step 5.
  8. request2 finally completes, and its results are used, because it active2 is still true.

Forked CodeSandbox with added console.log's that helped me sort it out.

huangapple
  • 本文由 发表于 2023年7月7日 01:30:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76631248.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定