score:343

Accepted answer

the pattern that you need to follow depends on your use case.

first: you might have a situation where you need to add event listener during the initial mount and clean them up at unmount and another case where a particular listener needs to be cleaned up and re-added on a prop change.

in such a case, using two different useeffect is better to keep the relevant logic together as well as having performance benefits

useeffect(() => {
   // adding event listeners on mount here
   return () => {
       // cleaning up the listeners here
   }
}, []);

useeffect(() => {
   // adding listeners everytime props.x changes
   return () => {
       // removing the listener when props.x changes
   }
}, [props.x])

second: you need to trigger an api call or some other side-effect when any of the state or props change from a defined set. in such a case a single useeffect with the relevant dependencies to monitor would be better

useeffect(() => {
    // side effect here on change of any of props.x or statey
}, [props.x, statey])

third: you need separate side-effect for different sets of changes. in such a case, separate out relevant side-effects into different useeffects

useeffect(() => {
   // some side-effect on change of props.x
}, [props.x])

useeffect(() => {
   // another side-effect on change of statex or statey 
}, [statex, statey])

score:13

it's perfectly fine to have have multiple useeffect.

here's how one of my setups looks like:

/*
 * backend tags list have changed add the changes if needed
 */
useeffect(() => {
    settagslist(settagsadded);
}, [settagsadded]);

/*
 * backend files have changed add the changes if needed
 */
useeffect(() => {
    for (let i = 0; i < changedfilesmeta.length; i += 1) {
        // is the list item value changed
        if (changedfilesmeta[i].id === currenteditablefile.id) {
            unstable_batchedupdates(() => {
                settags(changedfilesmeta[i].tags ? changedfilesmeta[i].tags : []);
            });
        }
    }
}, [changedfilesmeta]);

/*
 * reset when user select new files using the filepicker
 */
useeffect(() => {
    if (setnewfiles.length > 0) {
        unstable_batchedupdates(() => {
            setcurrentfile(null);
            setdescription('');
            settitle('');
            settags([]);
        });
    }
}, [setnewfiles]);

/*
 * user selecet to edit a file, change to that file
 */
useeffect(() => {
    // when user select a file to edit it
    if (currenteditablefile && currenteditablefile !== thecurrentfile) {
        setcurrentfile(currenteditablefile);
        unstable_batchedupdates(() => {
            setdescription(currenteditablefile.description);
            settitle(currenteditablefile.title);
            settags(currenteditablefile.tags);
        });
    }
}, [currenteditablefile]);

score:82

you should use multiple effects to separate concerns as suggested by reactjs.org.


Related Query

More Query from same tag