使用 setState 的 useEffect 挂钩的执行顺序

问题描述 投票:0回答:1

我在下面的 React 功能组件中有以下 useEffects。我想确保当更新 showComponentProp 时,第一个 useEffect 在运行第二个 useEffect 之前更新状态。

我知道 useEffect 挂钩按照它们在组件主体中出现的顺序运行,但是,由于它们包含 setState 函数,我不能 100% 确定其行为。我不希望 useEffect 挂钩中的两个 setState 函数之间存在竞争条件。

有人可以澄清调用 useEffects 的确切顺序以及在这种情况下何时重新渲染组件吗?例如,是否调用了第一个效果,当更新 isVisible 状态时,组件是否会在调用第二个效果之前重新渲染?在这种情况下,两个效果将在重新渲染后再次运行,或者仅运行第二个效果,因为之前调用了第一个效果。

任何参考资料将不胜感激,因为我找不到解释这一点的资源。

const [isVisible, setIsVisible] = useState(showComponentProp);

useEffect(() => {
    setIsVisible(showComponentProp);
}, [showComponentProp]);

useEffect(() => {
    if (showComponentProp && timerProp) {
      const timeout = setTimeout(() => setIsVisible(false), timerProp);
      return () => clearTimeout(timeout);
    }
}, [showComponentProp, timerProp]);
reactjs react-hooks
1个回答
0
投票

我想确保当

showComponentProp
更新时, 第一个
useEffect
在第二个 useEffect 之前更新状态 运行。

第一个

useEffect
钩子的回调肯定会在调用第二个isVisible钩子之前
enqueue
更新
useEffect
状态。

我知道

useEffect
钩子按照它们出现的顺序运行 然而,在组件主体中,因为它们包含 setState 函数, 我不能 100% 确定这种行为。我不想举行比赛
useEffect
钩子中两个 setState 函数之间的条件。

所有 React hooks 被称为每个渲染周期,按照它们定义的顺序。如果

showComponentProp
发生变化,那么由于它包含在 both
useEffect
钩子的依赖数组中,它将按照定义的顺序触发 both
useEffect
钩子的回调。

有人可以澄清一下 useEffects 的确切顺序吗 在这种情况下,当组件被重新渲染时被调用。为了 例如,是调用的第一个效果,当

isVisible
状态时 更新后,组件是否在第二个效果之前重新渲染 叫?在这种情况下,这两种效果都会在 重新渲染,或者只是调用第一个效果时的第二个效果 以前。

  1. 组件将按顺序渲染并调用所有 React hook。
  2. 在渲染周期结束时,将按顺序调用排队的
    useEffect
    钩子回调。
  3. Effect #1 回调会将
    isVisible
    状态更新排入队列以更新到当前
    showComponentProp
    值。
  4. Effect #2 回调将检查当前
    showComponentProp
    timerProp
    值,如果两者都为 true,则进入 if 块并实例化超时以将另一个
    isVisible
    状态更新排队为 false,并返回
    useEffect 
    钩子清理功能。
  5. 排队的状态更新将被处理并触发组件重新渲染:
    1. 返回上面的步骤1重复该过程
    2. 运行超时则:
      • timerProp
        毫秒后过期,并调用回调将另一个
        isVisible
        状态更新排队为 false,并触发另一个组件重新渲染,例如回到上面的步骤 1。
      • 过期前被清理功能取消

在任何情况下,每个渲染周期都会调用两个

useEffect
钩子,并且仅当依赖项发生变化时才会调用回调。

但是,我怀疑您可以在一个

useEffect
钩子中完成这一切,这可能会让理解逻辑和流程更容易一些。

const [isVisible, setIsVisible] = useState(showComponentProp);

// Run effect when either showComponentProp or timerProp update
useEffect(() => {
  // Only instantiate timeout when we've both truthy
  // showComponentProp and timerProp values
  if (showComponentProp && timerProp) {
    // Enqueue isVisible state update "now"
    setIsVisible(true);

    // Enqueue timeout to enqueue isVisible state update "later"
    const timeout = setTimeout(() => setIsVisible(false), timerProp);

    return () => clearTimeout(timeout);
  }
}, [showComponentProp, timerProp]);
© www.soinside.com 2019 - 2024. All rights reserved.