`useEffect` 的预期回报用于什么?

IT技术 reactjs ecmascript-6 react-hooks
2021-05-09 07:53:05

钩子的 React文档中,他们说:

“这还允许您使用效果内部的局部变量处理无序响应”

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. 在这个例子中被忽略的用途是什么?

谢谢!

4个回答

为什么返回是一个函数?返回 () => { 忽略 = 真 };

文档中

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

React 什么时候清理效果?当组件卸载时,React 执行清理。但是,正如我们之前所了解的,效果会在每次渲染时运行,而不仅仅是一次。这就是为什么 React 还会在下次运行效果之前清除上一次渲染中的效果。我们将在后面讨论为什么这有助于避免错误以及如何选择退出此行为以防它产生性能问题。

在这个例子中被忽略的用途是什么?

最初在useEffectHookignore中设置为,let ignore = false;fetchProduct函数执行时,它会检查ignoreistrue并相应地设置setProduct(json)这意味着我们已经using 中state调用product并设置了值状态用于在页面上呈现详细信息。 statesetProduct(json)product

注意:作为[productId]第二个参数传递给useEffectfetchProduct函数只会在productId更改时执行

请参阅通过跳过效果优化性能

我会在这里解释一下,因为我花了一些时间来理解上面的解释,所以我会尽量让它在其他人身上更简单。

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

2- 在这个例子中忽略了什么?
ignore被用作告诉忽略API调用或没有功能的标志。什么时候用?当你有竞争条件时。

[竞争条件的例子-你可以忽略这部分你已经熟悉竞争条件]例如你点击产品列表,当每个产品被点击时,如果你快速点击,你会用这个产品信息更新页面多次在产品中,使用效果将在product_id更改时更新,并且在某些时候单击 product1 [将为 product1 调用 api ] 然后快速 product2 [将为 product2 调用 api 并检索数据导致 -> setProduct(product2data) ) ] 而 product1 的数据刚刚到达导致 -> setProduct(product1data)这样我们就点击了 product2 !但是 product1 数据出现在页面上!!

屁股有什么关系ignore??
[逻辑解释]
ignore亲爱的,告诉setProduct忽略旧数据,不设置,这样我们只会设置最后点击的产品,即使旧数据到了。
[代码说明]
1-第一种情况:没有比赛,点击product1->ignore为false,调用api,检索数据,if(!ignore)->将设置product1数据,现在清理功能将设置ignore为true,恭喜!。

2-第二个场景 -> 竞争条件,点击 product1 -> ignore 为 false,调用 api,[数据仍未到达],现在点击 product2 忽略为 false,调用 api,数据到达,if( !ignore) -> will设置 product2 数据,清理函数将设置 ignore 为 true , product1 函数数据已到达 -> if( !ignore) -> 为 false OOOPS,不会设置product1数据“旧数据”。

这样我们将始终拥有新数据。CHEERRRRRRRRS :D

//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
    }
  } ,[])
}

我们使用一个布尔标志调用ignore让我们的数据获取逻辑知道组件的状态(挂载/卸载)。如果组件确实卸载了,则该标志应设置为 true,这会导致阻止在数据之后设置组件状态fetching 最终被异步解决了。当组件被卸载时,“返回”(useEffect 的第二部分)被调用。但是在这种情况下,由于依赖关系 [query] 当查询更改时,我们的组件会重新渲染,因此重新初始化 sideEffect。在您的 IDE 上运行此代码,然后在您的浏览器中像 chrome 一样打开 Devtools 并清除控制台,然后在输入单词 react 的输入中,尽快添加字符 2,然后立即删除字符 2。检查控制台以查看发生了什么。