【问题标题】:React useEffect executing last functionReact useEffect 执行最后一个函数
【发布时间】:2021-03-24 12:49:34
【问题描述】:

我需要有 2 个不同的函数,在开始时只更新 2 个不同的组件一次。因此,我使用useEffect。代码如下

const loadCategories = () => {
    getCategories().then((c) => setValues({ ...values, categories: c.data }));
}

const loadStores = () => {
    getStores().then((c) => setValues({ ...values, stores: c.data }));
}

useEffect(() => {
  loadStores();
  loadCategories();
}, []);

这两个函数都在设置下拉元素的值

问题是虽然两个函数都执行了,但只有loadCategories()函数逻辑反映在UI中。如何让这两个函数的逻辑都体现在 UI 中?

【问题讨论】:

  • useEffect 函数在 loadStores 内部吗?看起来你可能有无限递归?
  • 不,它在loadStores 之外。 2 个load 函数在useEffect 之外
  • 我可以得出结论的唯一原因是,loadCategories() 覆盖 loadStores() 但这不是导致categories 中的第一个设置状态和stores 中的第二个设置状态。您能否尝试仅运行第一个函数loadStories() 并检查该函数是否单独更新 UI。也许问题出在其中,或者在 UI 上应用时。
  • @PredragDavidovic 当我在useEffect 中只使用一个函数时,它工作正常,但是当我一个接一个地使用两个函数时,最后一个函数将在 UI 中反映出来,即使这两个函数跑了

标签: javascript reactjs use-effect


【解决方案1】:

第一个更好的做法是在 useEffect 中添加这些函数或将它们包装在 useCallback 钩子中。 其次,两者或您的函数都是承诺,因此每个可能不会同时解决,并且当您尝试更新状态值时将保持其初始值,这就是为什么您的第一个函数没有反映在 ui 中的原因,而是使用 setState callback 来获取之前的状态,例如这个:

useEffect(() => {
const loadCategories = () => {
    getCategories().then((c) => setValues(prevState=>({ ...prevState, categories: c.data })));
}

const loadStores = () => {
    getStores().then((c) => setValues(prevState=>({ ...prevState, stores: c.data })));
}
  loadStores();
  loadCategories();
}, []);

【讨论】:

    【解决方案2】:

    Promise 和 useEffect 可能具有挑战性,因为组件可能会在您承诺完成之前卸载。

    这是一个效果很好的解决方案:

    useEffect(() => {
      let isRunning = true;
      Promise.all([ 
        getCategories(),
        getStores()
      ]).then(([stores, categories]) => {
        // Stop if component was unmounted:
        if (!isRunning) { return }
        // Do anything you like with your lazy load values:
        console.log(stores, categories)
      });
      return () => {
        isRunning = false;
      }
    }, []);
    

    【讨论】:

      【解决方案3】:

      等待两个 Promise 解决,然后使用来自两者的数据更新您的状态,并以您认为合适的任何方式组合。

      useEffect(() => {
          Promise.all([getCategories(), getStores()]).then(([categories, stores]) => {
            setValues({categories, stores})
          });
      }, []);
      

      您之前遇到的问题(正如您所经历的)是values 始终是在此渲染上运行useState 时的值。

      如果您真的想单独进行更新,可以查看 useReducer:https://reactjs.org/docs/hooks-reference.html#usereducer

      【讨论】:

        【解决方案4】:

        你在对 React 的依赖关系撒谎。您的两个函数都依赖于values 状态变量。这也是它不起作用的原因:当钩子运行时,values 被关闭,然后当 setValues 运行时 values 发生变化(设置为新对象),但是在闭包内部它仍然引用旧值.

        您可以通过将回调传递给setValues 轻松解决这个问题,这样您就不会依赖外部并且值更新是原子的:

         setValues(values => ({ ...values, stores: c.data }));
        

        【讨论】:

        • 这行得通。我只能接受一个答案。因此,我投了赞成票
        猜你喜欢
        • 2021-12-05
        • 1970-01-01
        • 2022-06-15
        • 1970-01-01
        • 2022-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多