gene b.
gene b.

Reputation: 11974

React Functional Component Lifecycle Flow with useEffect, both [] and [var]

My functional component is structured as follows:

// Initialization
useEffect(() => {
    fetchDetailedUserInfo();
  }, []);

// Update on initialization of detailedUserInfo
useEffect(() => {
    if (detailedUserInfo) {
      //...
      setInitialFormValues(..);
    }
  }, [detailedUserInfo]);

// Update on initialization of initialFormValues
useEffect(() => {
    //...
  }, [initialFormValues]);
  
// Return JSX
return (  .. );

What determines when the render (return) runs in between all these useEffects, and how are the useEffects ordered among themselves? What is the exact flow?

Upvotes: 2

Views: 108

Answers (2)

M.Calugaru
M.Calugaru

Reputation: 442

The first useEffect runs when the component is first rendered, so will fire first. The second useEffect will fire whenever detailedUserInfo has changed its value (assuming its not null/false, etc.). The third useEffect will fire whenever initialFormValues has changed its value.

Upvotes: 0

albseb
albseb

Reputation: 169

According to docs:

By default, effects run after every completed render, but you can choose to fire them only when certain values have changed.

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. In our example, this means a new subscription is created on every update. To avoid firing an effect on every update, refer to the next section.

A lot of people tend to miss the above statement on the documentation.

There are two behaviours to be noticed.

  • When there is an empty dependency array [] In this case the cleanup effect will only get called when the component is going to unmount
  • When there is some dependency in the dep array In this case, the cleanup effect is called everytime the useEffect is triggered due to the update phase, it will be called first, then the callback function will be called, so as to ensure that any cleanup is done before the next callback is called.

The main reason for this confusion is that when someone comes from class components this is not the case, and they tend to follow the lifecycle diagram provided.

The hooks LC diagram is not really official, and has a small flaw

https://github.com/Wavez/react-hooks-lifecycle/issues/5

I had raised an issue on the github repo as well with the correction. Its still open though.

Do checkout the docs here

https://reactjs.org/docs/hooks-reference.html#cleaning-up-an-effect

why dont you do something like this instead?

useEffect(() => {
    // you can return the promise inside the fetchDetailedUserInfo function, and ensure that you return the reponse. make sure to add a catch block or handle that in the response.
    fetchDetailedUserInfo()
    .then(res=>{
       setInitialFormValues(...)
     })
}, []);

Upvotes: 1

Related Questions