React Hook – multiple “useEffect” fires at componentDidMount

Tags: , , ,



I’m using multiple useEffect hooks to perform the componentDidMount and componentDidUpdate functionalities, however, looks like when component loads, all my useEffect fires initially…

const testComp = () => {
   const stateUserId = useSelector(state => { return state.userId; });
   const [userId, setUserId] = useState(stateUserId);
   const [active, setActive] = useState(false);
   const [accountId, setAccountId] = useState();
   
   useEffect(() => {
      console.log('component did mount...');
   }, [userId]);
   
   useEffect(() => {
      console.log('should trigger when userId changes...');
   }, [userId]);

   useEffect(() => {
      console.log('should trigger when active changes...');
   }, [active]);
   
   useEffect(() => {
      console.log('should trigger when accountId changes...');
   }, [accounted]);
  
   return (<div>...</div);
}

when my component mounts, I see all those console log there

component did mount...
should trigger when userId changes...
should trigger when active changes...
should trigger when accountId changes...

How could I only let my first useEffect fires, but the other three fires when the dependency changes only?

Answer

useEffect is not a direct replacement of componentDidMount and componentDidUpdate. Effect will run after each render, which is why you are seeing all those console logs. According to the React documentation, the second parameter of useEffect means

you can choose to fire them (effects) only when certain values have changed.

After the initial render, if the component is rendered again, only effects watch the corresponding value changes are triggered.

One way to achieve what you want is by creating additional variables to host initial values and do comparisons in the useEffect when you need to.

const testComp = () => {
  const initUserId =  useSelector(state => { return state.userId; });
  const stateUserId = initUserId;
   const [userId, setUserId] = useState(stateUserId);
   
   useEffect(() => {
      console.log('component did mount...');
   }, [userId]);
   
   useEffect(() => {
      if (userId !== initUserId) {
        console.log('should trigger when userId changes...');
      }
      
   }, [userId]);
  
   return <div>...</div>
}


Source: stackoverflow