0

I have numerous useStates in my app. I am using useEffect to dispatch an action to my reducer. Instead of using a single useEffect for each change to useState, I would like to, for efficiency and readability sake, put all the state changes in a single useEffect. It does not seems to work as I invisioned. What is the correct syntax to make it functional

const [nameFirst, setNameFirst] = useState('');
const [nameLast, setNameLast] = useState('');
const [nameEmail, setNameEmail] = useState('');
const [namePhone, setNamePhone] = useState('');

useEffect(() => {
    if (nameFirst) {
        dispatch({ type: "NAME_FIRST", nameFirst: nameFirst });
    } else if (nameLast) {
        dispatch({ type: "NAME_LAST", nameLast: nameLast });
    } else if (nameEmail) {
        dispatch({type: "NAME_EMAIL", nameEmail: nameEmail});
    } else if (namePhone) {
        dispatch({type: "NAME_PHONE", namePhone: namePhone});
    }
}, [nameFirst, nameLast, nameEmail, namePhone]);

What I would like to avoid is something like...

useEffect(() => {
        dispatch({ type: "NAME_FIRST", nameFirst: nameFirst });
}, [nameFirst]);

useEffect(() => {
        dispatch({ type: "NAME_LAST", nameLast: nameLast });
}, [nameLast]);

useEffect(() => {
        dispatch({type: "NAME_EMAIL", nameEmail: nameEmail});
}, [nameEmail]);

useEffect(() => {
    dispatch({type: "NAME_PHONE", namePhone: namePhone});
}, [namePhone]);

As it doesn't seem very DRY

IWI
  • 1,528
  • 4
  • 27
  • 47

3 Answers3

2

you want to fire useEffect if one of the effect's dependancy is changed. not others. the simplest approach is use multiple useEffects. but the if & else if is incorrect & will not work.

I think you want this & actually the correct question is:
React useEffect Fire Hook when only one of the effect's deps changes, but not the others

some solutions:

one solution is compare prevState with nextState and if there is a change, fire that!

sepehr
  • 210
  • 1
  • 2
  • 8
1

The first approach uses else if so it means you only update one of them; maybe you wish to update more than one?

Nevertheless, I actually prefer the 2nd approach; it's easier to read what each useEffect should do

Finally, have you considered using redux hook useSelector instead of useState? Unless you are doing something extra when updating the state useSelector should be the best option for you

Luis Filipe
  • 8,488
  • 7
  • 48
  • 76
0

How about this code?

const [data, setData] = useState({
    nameFirst: "",
    nameLast: "",
    nameEmail: "",
    namePhone: "",
});

useEffect(() => {
    setData(() => {
      data.nameFirst && dispatch({ type: "NAME_FIRST", nameFirst: nameFirst });
      data.nameLast && dispatch({ type: "NAME_LAST", nameLast: nameLast });
      data.nameEmail && dispatch({type: "NAME_EMAIL", nameEmail: nameEmail};
      data.namePhone && dispatch({type: "NAME_PHONE", namePhone: namePhone});
      return data;
    })
}, [data]);
Stark Jeon
  • 1,107
  • 9
  • 24