有多个 useEffect 时跳过第一个 useEffect [英] Skip first useEffect when there are multiple useEffects

查看:28
本文介绍了有多个 useEffect 时跳过第一个 useEffect的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了限制 useEffect 在第一次渲染时运行,我们可以这样做:

To restrict useEffect from running on the first render we can do:

  const isFirstRun = useRef(true);
  useEffect (() => {
    if (isFirstRun.current) {
      isFirstRun.current = false;
      return;
    }

    console.log("Effect was run");
  });

根据此处的示例:https://stackoverflow.com/a/53351556/3102993

但是如果我的组件有多个 useEffects,每个 useEffects 处理不同的 useState 变化怎么办?我已经尝试在另一个 useEffect 中使用 isFirstRun.current 逻辑,但由于一个返回,另一个仍然在初始渲染上运行.

But what if my component has multiple useEffects, each of which handle a different useState change? I've tried using the isFirstRun.current logic in the other useEffect but since one returns, the other one still runs on the initial render.

一些上下文:

const Comp = () => {
const [ amount, setAmount ] = useState(props.Item ? Item.Val : 0);
const [ type, setType ] = useState(props.Item ? Item.Type : "Type1");

useEffect(() => {
    props.OnAmountChange(amount);
}, [amount]);

useEffect(() => {
    props.OnTypeChange(type);
}, [type]);

return {
    <>
        // Radio button group for selecting Type
        // Input field for setting Amount
    </>
}
}

我为每个使用单独的 useEffects 的原因是因为如果我执行以下操作,它不会更新数量.

The reason I've used separate useEffects for each is because if I do the following, it doesn't update the amount.

useEffect(() => {
    if (amount) {
        props.OnAmountChange(amount);
    } else if (type) {
        props.OnTypeChange(type)
    }
}, [amount, type]);

推荐答案

据我所知,你需要控制 useEffect 逻辑在第一次挂载和连续重新渲染时的执行.您想跳过第一个 useEffect.效果在组件渲染后运行.

As far as I understand, you need to control the execution of useEffect logic on the first mount and consecutive rerenders. You want to skip the first useEffect. Effects run after the render of the components.

因此,如果您正在使用此解决方案:

So if you are using this solution:

const isFirstRun = useRef(true);
  useEffect (() => {
    if (isFirstRun.current) {
      isFirstRun.current = false;
      return;
    }

    console.log("Effect was run");
  });
   useEffect (() => {
    // second useEffect
    if(!isFirstRun) {
        console.log("Effect was run");
     }
   
  });

因此,在这种情况下,一旦将 isFirstRun ref 设置为 false,对于所有连续效果,isFirstRun 的值都会变为 false,因此所有效果都会运行.

So in this case, once isFirstRun ref is set to false, for all the consecutive effects the value of isFirstRun becomes false and hence all will run.

你可以做的是,使用类似 useMount 自定义 Hook 的东西,它可以告诉你它是第一次渲染还是连续重新渲染.下面是示例代码:

What you can do is, use something like a useMount custom Hook which can tell you whether it is the first render or a consecutive rerender. Here is the example code:

const {useState} = React

function useMounted() {
  const [isMounted, setIsMounted] = useState(false)


  React.useEffect(() => {
    setIsMounted(true)
  }, [])
  return isMounted
}

function App() {


  const [valueFirst, setValueFirst] = useState(0)
  const [valueSecond, setValueSecond] = useState(0)

  const isMounted = useMounted()

  //1st effect which should run whenever valueFirst change except
  //first time
  React.useEffect(() => {
    if (isMounted) {
      console.log("valueFirst ran")
    }

  }, [valueFirst])


  //2nd effect which should run whenever valueFirst change except
  //first time
  React.useEffect(() => {
    if (isMounted) {
      console.log("valueSecond ran")
    }

  }, [valueSecond])

  return ( <
    div >
    <
    span > {
      valueFirst
    } < /span> <
    button onClick = {
      () => {
        setValueFirst((c) => c + 1)
      }
    } >
    Trigger valueFirstEffect < /button> <
    span > {
      valueSecond
    } < /span> <
    button onClick = {
      () => {
        setValueSecond((c) => c + 1)
      }
    } >
    Trigger valueSecondEffect < /button>

    <
    /div>
  )
}

ReactDOM.render( < App / > , document.getElementById("root"))

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

希望能帮到你!!

这篇关于有多个 useEffect 时跳过第一个 useEffect的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆