最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - When is the cleanup function triggered when using useEffect hook with dependencies? - Stack Overflow

programmeradmin1浏览0评论

I'm using a useEffect to show a UI Loading... but only after 250ms. It works ... but I really don't understand why and specially how and when useEffect invokes the returned function (that clears the timeout).

Well ... I'm not sure that's work perfectly. Sometimes the "Loading ..." message should appear but it's not.

 const [loadingAfterShortTime, setLoadingAfterShortTime] = useState(false);

 useEffect(() => {
  setLoadingAfterShortTime(bool => false);
  if (myDepandanceToTrigTheLoadingWord === true) {
    const id = setTimeout(() => {
      setLoadingAfterShortTime(bool => true);
    }, 250);
    return () => {
      clearTimeout(id);
    };
  }
}, [myDepandanceToTrigTheLoadingWord]);

I'm using a useEffect to show a UI Loading... but only after 250ms. It works ... but I really don't understand why and specially how and when useEffect invokes the returned function (that clears the timeout).

Well ... I'm not sure that's work perfectly. Sometimes the "Loading ..." message should appear but it's not.

 const [loadingAfterShortTime, setLoadingAfterShortTime] = useState(false);

 useEffect(() => {
  setLoadingAfterShortTime(bool => false);
  if (myDepandanceToTrigTheLoadingWord === true) {
    const id = setTimeout(() => {
      setLoadingAfterShortTime(bool => true);
    }, 250);
    return () => {
      clearTimeout(id);
    };
  }
}, [myDepandanceToTrigTheLoadingWord]);
Share Improve this question edited Oct 7, 2019 at 12:22 red0ct 5,0553 gold badges22 silver badges46 bronze badges asked Mar 13, 2019 at 17:51 Benoit LEGER-DERVILLEBenoit LEGER-DERVILLE 6631 gold badge6 silver badges10 bronze badges 3
  • 1 Hey, I just reworded your title to be in the form of a question. Feel free to modify it if you don't think I did a good job preserving the intent of the original question. – Retsam Commented Mar 13, 2019 at 18:44
  • The cleanup function is called whenever the dependencies change, and when the component is unmounted. – Felix Kling Commented Mar 13, 2019 at 18:46
  • So ... outside the case where the component is unmounted, all stuff include into the useEffect function, including the return statement, is call at every dependencie change ? – Benoit LEGER-DERVILLE Commented Mar 13, 2019 at 20:28
Add a comment  | 

3 Answers 3

Reset to default 13

The explanation provided by @Powell Ye is good however there a bit of erroneous information specifically when speaking about re-renders (e.g. when props change)

consider some simple component with the following

    useEffect( () => {
        console.log('Effect is applied')
        //some logic
        return () => {
            console.log('cleaning up')
            //cleanup logic
        }
    })
    return (<>
        {console.log('rendering...')}
     </>)

say the props passed in changes you might think it goes as such

  1. 'cleaning up'
  2. new props
  3. 'rendering...'
  4. 'Effect is applied'

However, the following actually occurs

  1. new props
  2. 'rendering...'
  3. 'cleaning up'
  4. 'Effect is applied'

That is, the clean up function runs AFTER the new render/painting but BEFORE the 'new' effects are applied, the docs can be a bit ambigious about this

the previous effect is cleaned up before executing the next effect

This is done for performance reasons => so that rendering is not delayed ( it can be frustrating at times for me too )

Here's an outline of the timings involved:

  • useEffect is called on the initial render and whenever any of the values it depends on change. In general, it fires after the rendering is completed. If you think of it in terms of a class-based component, equivalent would be componentDidMount method.
  • The function returned from within useEffect is invoked before the component is removed from the UI or is about to re-render (to avoid memory leaks). Previous effect is always cleaned up before performing the next effect. It's guaranteed to run before any new renders. Equivalent would be componentWillUnmount.

Example

Let's assume that there is a useEffect with few dependencies made of props (which are passed to our component) + a cleanup function. On the first render, the following would happen:

  • Once the component is mounted, code inside effect's body will run;
  • Cleanup function stays put, ready to run before the component re-renders / is removed from the screen.

Now let's imagine something triggers a re-render. Since it's listed as something useEffect depends on, the effect will be re-executed as following:

  • Cleanup function executes after rendering is completed;
  • Right after that, code inside effect's body will run;
  • New cleanup function is created, again, ready to execute after the component re-renders / or before it's removed from the screen.

As per the react documentation,

Cleaning up an effect

The clean-up function runs before the component is removed from the UI to prevent memory leaks. Additionally, if a component renders multiple times (as they typically do), the previous effect is cleaned up before executing the next effect.

Timing of effects

React will always flush a previous render’s effects before starting a new update.

As per my understanding from both the quotes, cleanup runs after the effect is applied and before the component is unmounted (removed from UI).

发布评论

评论列表(0)

  1. 暂无评论