【问题标题】:What happens for an useEffect with no second argument or one equal to null or undefined?没有第二个参数或等于 null 或未定义的 useEffect 会发生什么?
【发布时间】:2022-10-31 16:58:43
【问题描述】:

我只是想知道如果我们将第二个参数作为nullundefined 来代替依赖项数组,useEffect 将如何表现。它会在每个周期渲染吗?还是只有一次?任何线索将不胜感激。

【问题讨论】:

    标签: javascript reactjs react-hooks frontend


    【解决方案1】:

    如果您创建一个没有第二个参数的useEffect,或者一个等于undefinednull,则回调将在每次渲染时执行。如果您已明确键入 undefinednull 作为第二个参数,并且您的编辑器中有 Eslint,您将收到以下警告:

    React Hook useEffect was passed a dependency list that is not an array literal. This means we can't statically verify whether you've passed the correct dependencies. (react-hooks/exhaustive-deps)
    

    在像下面这样的情况下,如果您没有在回调中改变 state,这对您的应用程序没有任何伤害,它只会在每次渲染时记录“Hello Word”。

    export default function App() {
      const [state, setState]= useState(true);
      useEffect(() => {
        console.log("Hello Word");
      });
      return (
        <div>
          <button onClick = {()=>setState(!state)}>Toggle State</button>
        </div>
      );
    }
    

    在以下情况下,当您在回调中更改 state 时,它将导致渲染的无限循环。这是因为状态更改会触发渲染,并且在每次渲染时都会执行回调。

    export default function App() {
      const [state, setState]= useState(true);
      useEffect(() => {
       setState(!state);
      });
      return (
        <div>
          <button onClick = {()=>setState(!state)}>Toggle State</button>
        </div>
      );
    }
    

    为了涵盖所有用例,有一个使用空依赖数组作为第二个参数的用例,其中回调仅在第一次渲染时执行:

    export default function App() {
      const [state, setState]= useState(true);
      useEffect(() => {
       setState(!state);
      },[]);
      return (
        <div>
          <button onClick = {()=>setState(!state)}>Toggle State</button>
        </div>
      );
    }
    

    最后,在第一次渲染时调用回调的那个,并且每次依赖数组中的一些 state 发生变化时:

    export default function App() {
      const [state, setState]= useState(true);
      useEffect(() => {
       console.log("Hello Word");
       // setState(!state); if you mutate state here, it will cause an infinite loop of renders
      },[state]);
      return (
        <div>
          <button onClick = {()=>setState(!state)}>Toggle State</button>
        </div>
      );
    }
    

    【讨论】:

      【解决方案2】:

      如果 deps 未定义或为空,它将重新渲染每个圆圈。

      在 react 源中,当第二个参数未定义时,deps 将为nullupdateEffectImpl,将始终执行 pushEffect,并渲染每个圆圈:

      function updateEffectImpl(fiberFlags, hookFlags, create, deps): void {
        const nextDeps = deps === undefined ? null : deps;
      
        if (currentHook !== null) {
          // .eg
        }
      
        // always execute
        hook.memoizedState = pushEffect(
          HookHasEffect | hookFlags,
          create,
          destroy,
          nextDeps,
        );
      }
      

      【讨论】:

        猜你喜欢
        • 2019-05-05
        • 2011-08-21
        • 2018-07-20
        • 1970-01-01
        • 2020-04-02
        • 1970-01-01
        • 2019-10-29
        • 2021-04-02
        • 2012-09-28
        相关资源
        最近更新 更多