Why is the cleanup function from `useEffect` called on every render?

前端 未结 5 1224
礼貌的吻别
礼貌的吻别 2020-12-18 18:29

I\'ve been learning React and I read that the function returned from useEffect is meant to do cleanup and React performs the cleanup when the component unmounts

5条回答
  •  温柔的废话
    2020-12-18 19:06

    The React docs have an explanation section exactly on this.

    In short, the reason is because such design protects against stale data and update bugs.

    The useEffect hook in React is designed to handle both the initial render and any subsequent renders (here's more about it).


    Effects are controlled via their dependencies, not by the lifecycle of the component that uses them.

    Anytime dependencies of an effect change, useEffect will cleanup the previous effect and run the new effect.

    Such design is more predictable - each render has its own independent (pure) behavioral effect. This makes sure that the UI always shows the correct data (since the UI in React's mental model is a screenshot of the state for a particular render).

    The way we control effects is through their dependencies.

    To prevent cleanup from running on every render, we just have to not change the dependencies of the effect.

    In your case concretely, the cleanup is happening because array is changing, i.e. Object.is(oldArray, newArray) === false

    useEffect(() => {
      // ...
    }, [array]);
    //  ^^^^^ you're changing the dependency of the effect
    

    You're causing this change with the following line:

    useEffect(() => {
      const id = setInterval(() => {
        setArray(array.concat("hello")); // <-- changing the array changes the effect dep
      }, 3000);
      myRef.current = id;
    
      return () => {
        clearInterval(myRef.current);
      };
    }, [array]); // <-- the array is the effect dep
    

提交回复
热议问题