“ useEffect”的预期返回值是用来做什么的?

在反应 文件的钩子,他们说:

”这还允许您使用本地 效应内部的变量”

useEffect(() => {
let ignore = false;
async function fetchProduct() {
const response = await fetch('http://myapi/product/' + productId);
const json = await response.json();
if (!ignore) setProduct(json);
}


fetchProduct();
return () => { ignore = true };
}, [productId]);

演示应用

请解释一下,帮助我更好地理解这一点:

  1. 为什么返回是一个函数? return () => { ignore = true };
  2. 这个例子中忽略了什么?

谢谢!

71790 次浏览

为什么返回是一个函数? return () => { ignore = true };

医生,

为什么我们从我们的效果返回一个函数?这是效果的可选清除机制。每个效果都可以返回一个函数,在它之后进行清理。这使我们可以保持添加和删除订阅的逻辑相互靠近。它们是同一效应的一部分!

还有

到底什么时候反应清除一个效果?React 在卸载组件时执行清理。然而,正如我们前面所了解的,每个渲染效果都会运行,而不仅仅是一次。这就是为什么在下次运行效果之前,React 还会清除之前渲染的效果。我们将讨论为什么这有助于避免 bug,以及如何选择不执行这种行为,以防它在后面创建性能问题。

这个例子中忽略了什么?

最初在 useEffectignore是这样设置的,let ignore = false;。 当执行 fetchProduct函数时,它检查 ignore是否为 true,并相应地设置 setProduct(json)。这意味着我们有 state称为 product,并使用 setProduct(json)state中设置值。此状态的 product用于在页面上呈现详细信息。

注意: [productId]作为第二个参数传递给 useEffect时,fetchProduct函数只有在 productId改变时才会执行。

参见 通过跳跃效应优化性能

当组件被卸载时,然后调用 return (useEffect 的第二部分)。但是在这种情况下,由于查询更改时的依赖项[ query ] ,我们的组件将被重新呈现,因此 sideEffect 将被重新初始化。 在 IDE 上运行 这个密码,然后在浏览器中打开 Devtools,比如 chrome 和 clear 控制台,然后输入写有 react的单词,尽快添加 char 2,然后立即删除 char 2。检查控制台看看发生了什么。

我们使用一个名为 ignore的布尔标志来让我们的数据获取逻辑知道组件的状态(挂载/卸载)。如果组件确实卸载了,那么标志应该设置为 true,这会导致在数据获取最终被异步解析之后无法设置组件状态。当组件被卸载时,调用“ return”(useEffect 的第二部分)。但是在这种情况下,由于查询更改时的依赖项[ query ] ,我们的组件将被重新呈现,因此 sideEffect 将被重新初始化。在 IDE 上运行 这个密码,然后在浏览器中打开 Devtools,比如 chrome 和 clear 控制台,然后在输入框中写入单词 response,尽快添加 char 2,然后立即删除 char 2。检查控制台看看发生了什么。

//all imports
function mufunc(){
useEffect(()=>{
const a = addEventListner('mouse' , console.log('mouse moves') )  //it prints when
//mouse moves
return ()=>{
removeEventListner(a)  //whenever the component removes it will executes
}
} ,[])
}

我将在这里解释它,因为 我花了一段时间才明白上面的解释,所以我将尽量使其他人更简单。

回答你的问题:
1-为什么返回是一个函数? return () => { ignore = true };
useEffect 提供了返回函数的使用,它用于清理函数的目的,OK!,你什么时候需要打扫?如果你订阅了一些东西,并且你想退订,例如,你应该添加退订逻辑的“返回函数”在 useEffect 内,而不是把逻辑放在其他地方,这可能会导致竞争条件!

这个例子中忽略了什么?
ignore用作一个标志,告诉函数忽略 api 调用与否。那是什么时候用的?当你有一个比赛条件。< br >

例如,你点击产品列表,当你点击每个产品时,你会更新这个产品信息页面,如果你在产品中快速点击多次,那么当 product_id改变时,useEffect 将会更新,在某个时刻点击 product1[将调用 product1的 api ] ,然后快速调用 product2[将调用 product2的 api 并检索数据 造成-> setProduct (product2data)] ,而 product1的数据刚刚到达 造成-> setProduct (product1data)。这样我们的产品就点击了!但是 product1数据出现在页面上! !.

但这和 ignore有什么关系?
[逻辑解释]
亲爱的,ignore告诉 setProduct 忽略旧数据,而不是设置它,这样我们只设置最后点击的产品,即使旧数据到达较晚。
[代码解释]
1-第一个场景: 没有比赛,product1被点击-> ignore是假的,调用 api,检索数据,如果(!ignore)-> 将设置 product1数据,现在清理函数将设置 ignore为真,恭喜!.

2秒场景-> 比赛条件,product1被点击-> 忽略是假的,调用 api,[数据仍然没有到达] ,现在 product2被点击忽略是假的,调用 api,数据到达,如果(!ignore)-> 将设置 product2数据,清除函数将设置忽略为真,product1函数数据已经到达-> 如果(!ignore)-> 是假的 哎呀,将不设置 product1数据“旧数据”。

这样我们总是有新的数据

useEffect 每次渲染都不执行一次当您想在执行后续效果之前清理前一次渲染的效果时,就需要返回一个具有清理逻辑的函数。

对于第二个问题 ——这个例子中忽略了什么:

它用于确保 翻译的最新值是状态更新所依赖的值,主要是在同时处理多个请求时。在这种情况下,在每个正在处理的请求发送响应后,除了 URL 包含最新更新的 翻译值的请求之外,忽略值将为 真实。(在这种情况下,忽略将保持为 < strong > false )

现在让我们讨论一下上面的代码:

我们知道 useEffect 在下一个 effect 运行之前运行返回声明的函数。让我们假设 翻译的值有两个变化发生得如此之快(可能是由于快速输入类型,它会在每次变化时更新值)。对于第一次更新,效果将运行并将 忽略设置为 < strong > false 。假设在成功处理获取请求并为响应分配一个值之前,发生对 翻译的第二次更改。在这里,我们的旧效果返回的函数将运行,并分配 真实忽略,然后,与 翻译的新值相关的新效果也将运行,将 < strong > false 分配给 忽略,并使用我们的新 翻译继续处理获取请求。但是,旧效果的 忽略 * 值现在是 真实,这意味着在获得响应之后,状态更新将被忽略(!忽略 = 错误)。对于新的效果,如果一个成功的响应带着数据到达,并且在 翻译值发生任何变化之前代码执行继续到 if 语句,那么 忽略将保持为 < strong > false (!而且我们的状态将使用最新的 翻译值进行更新。

返回函数是 清理功能,或者当 用户离开页面和组件卸载时。数组是最后一部分,您可以将在整个组件生命周期中更新的状态放在数组中。
为了更多