【问题标题】:question on code snippet useEffect with fetching state关于获取状态的代码片段 useEffect 的问题
【发布时间】:2021-03-31 02:10:39
【问题描述】:

我正在阅读从反应文档页面 https://reactjs.org/docs/hooks-faq.html#how-can-i-do-data-fetching-with-hooks 链接的代码截图 https://reactjs.org/docs/hooks-faq.html#how-can-i-do-data-fetching-with-hooks

这段代码我看不懂,返回的函数修改了忽略变量

  useEffect(() => {
    let ignore = false;

    async function fetchData() {
      const result = await axios('https://hn.algolia.com/api/v1/search?query=' + query);
      if (!ignore) setData(result.data);
    }

    fetchData();
    return () => { ignore = true; }
  }, [query]);

一旦第二次调用传递给 useEffect 的函数,就不会忽略 reset 回 false ,而忽略 ignore = true 完全无用。上面的代码不适合我。谢谢你的解释。

【问题讨论】:

  • 更多关于清理功能的信息here

标签: reactjs react-hooks


【解决方案1】:

ignored 变量在函数范围内,当前效果的 ignored 将是与下一个效果中的不同的实例。

【讨论】:

    【解决方案2】:

    如果一个效果返回一个清理函数,React 会在组件卸载时调用它,或者在效果因依赖项更改而重新运行之前调用它(如果 query 在这种情况下发生更改)。

    axios fetch 调用是异步的,因此在数据请求完成之前,组件可能会卸载或依赖项(例如查询)已更改。

    如果发生这种情况,返回的函数会将 ignore 设置为 true,并且 fetchData 函数不会尝试在卸载的组件上调用 setData。 (尝试更新已卸载组件的状态会导致错误。)

    来自the docs

    React 究竟何时清理效果? React 在组件卸载时执行清理。然而,正如我们之前所了解的,效果会为每次渲染运行,而不仅仅是一次。这就是为什么 React 还会在下次运行效果之前清理上一次渲染中的效果。

    由于javascript closures的工作方式,清理函数可以访问封闭范围内的ignore变量。

    当效果再次运行时,new 忽略变量被声明为使用引用新变量的新清理函数。

    【讨论】:

      【解决方案3】:

      你对函数调用和变量赋值的理解是正确的,但是你忘记了异步调用的威力:)

      useEffect 在需要的时候被调用(例如componentDidMount,componentDidUpdate by query 关键字),所以我们大致有

      1. 忽略=假
      2. 函数 fetchData 现已定义
      3. 函数 fetchData 被调用

      将 useEffect 的重置保持在脑海中。

      假设发生了导致重新渲染的事情,例如prop-change(但不是查询),甚至使用新获取的数据调用该 setData。

      你的 useEffect 不会有任何影响,导致 query shallow-comparison 找不到与前一个的变化。所以在这种情况下忽略的目的不涉及,因为它根本不会改变。

      此外,如果查询以任何方式发生变化,则函数执行大致(忽略事件循环,暂时执行宏任务)类似于:

      // ignore is false and for some reason query changes...
      
      (() => { ignore = true })() // ignore = true
      // continue running useEffect again.
      // lets think nothing else will happend in gap
      ignore = false // ignore = false
      

      我能想到的唯一可能的场景是当你的 useEffect 回退被调用时你的组件将被卸载。所以这是异步关键字想要恢复其尊严的时候?️。

      记住:异步函数不会通过您的命令返回任何内容。 想象一下,当您的组件完全从 DOM 中移除时数据到达,这就是 ignore=true 在此 useEffect 中所扮演的角色。

      防止未安装组件上的 setData

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-04-14
        • 1970-01-01
        • 2020-10-09
        • 1970-01-01
        • 2019-10-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多