bijoy tv
bijoy tv

Reputation: 158

How to handle, after state change in React context dispatch

I have a react version 16 application. The state changes are handled using React's Context, reducer concept.

To change the state and do something post that change can be handled as given below. For Example - I am in component 'Contact'. Inside this I am dispatching a state change on a variable age which is a number as given below -

dispatch({
    type: "CHANGE_AGE",
    payload: age
})

and catch the dispatch in the reducer as given below

case "CHANGE_AGE":
    return {
        ...state,
        age: action.payload
    }

To do something in 'Contact' component after there is a change in age, we can use 'useEffect' to watch for change in 'age'

useEffect({
    //doSomething()
},[state.age])

The problem is - What if we had to change an object in state, ie instead of changing the age, we had to change the address like given below and we had to do something after address has changed.

How do we watch for a change in address?

dispatch({
    type: "CHANGE_ADDRESS",
    payload: {
        city: "Delhi",
        country: "India",
        zip: '22233'
    }
})

One probable solution - Along with address dispatch, we can dispatch a variable, on change of which we can do something. But this is not a perfect solution.

Upvotes: 1

Views: 1765

Answers (1)

Rostyslav
Rostyslav

Reputation: 2866

Just store both: the previous and the current addresses

// your-state.js
const initialState = {
  age: 0,
  prevAdress: {
    city: '',
    country: '',
    zip: ''
  },
  currAdress: {
    city: '',
    country: '',
    zip: ''
  },
  ...
}

and when you dispatch, write current as previous in a reducer

// your-reducer.js
...
case "CHANGE_ADDRESS":
    return {
        ...state,
        prevAddress: { ...state.currAddress },
        currAddress: { ...action.payload }
    }

Then compare in the effect

// your-component.js
...
useEffect(() => {
  if (state.prevAddress.zip !== state.currAddress.zip) { // just an example of comparison
    // doSmthg
  }
}, [state]);
...

UPDATE

If you need to compare address only once and do something based on that comparison then just compare before dispatching a value:

// your-component.js
...
useEffect(() => {
  const doDispatch = () => dispatch({
        type: "CHANGE_ADDRESS",
        payload: {
          city: "Delhi",
          country: "India",
          zip: newZip,
        },
      });

  if (state.address.zip !== newZip) {
    doSmthgAsPromise().then(() => {     // do something and then dispatch
      doDispatch();
    });
  } else {
    doDispatch();
  }
}, [state, dispatch, doSmthgAsPromise]);

Upvotes: 1

Related Questions