Home > front end >  Is it normal Redux removes a local state in this situation?
Is it normal Redux removes a local state in this situation?

Time:04-29

I'm struggling to understand Redux and am loosing a local state upon hitting a button on a React page. The situation is as follows:

Suppose you are on a React page, which has a local state:

{"player": "PersonA"}

There's also a button on the same React page. Pushing the button triggers a Redux action. The associated controller method returns:

return res.status(200).json({
    statusCode: 200,
    success: true,
    payment: {"amount": "3", "currency": "EUR"},
});

And the reducer:

case APPLY_SUCCESS:
    console.log(...state); // returns undefined
    return { ...state, paymentData: action.payload.payment };

After hitting the button on the React page, the local state only contains paymentData. So player is gone from the local state. I thought ...state in the reducer should ensure maintaining the existing local state that is unaffected by the action. So it would just append paymentData to the local state and also keep player.

My question:

  • Am I correct that ...state in the reducer is supposed to ensure that the local state that is unaffected by the action, remains part of the local state?
  • If so, what could be the reason ...state is undefined? How can I ensure player is still part of the local state?

CodePudding user response:

console.log(...state) might throw a type error, because spreading is usually done inside arrays and object.

However the second part where you return {...state, paymentData: data} should work as you expect, with only paymentData being changed from state, since {...state} is simply making a shallow copy of the state object (not deep), and then replacing the paymentData key in this copy.

If you are working with a deeply nested key, I would look into lodash's deepClone function to create a deep copy of the state, and not a shallow copy, to prevent writing directly to redux state (and creating unexpected bugs)

Recommendation:

Check if console.log(state) is undefined or is an empty object.

If that's the case, state is not being passed into the reducer, or initialized properly, and you should check how it's being passed in.

Ensure that the reducer is following this model to initialize it properly. This is taken from redux's own docs and you can look at more examples there.

const initialState = {
  todos: [
    { id: 0, text: 'Learn React', completed: true },
    { id: 1, text: 'Learn Redux', completed: false, color: 'purple' },
    { id: 2, text: 'Build something fun!', completed: false, color: 'blue' }
  ],
  filters: {
    status: 'All',
    colors: []
  }
}

// Use the initialState as a default value
export default function appReducer(state = initialState, action) {
  // The reducer normally looks at the action type field to decide what happens
  switch (action.type) {
    // Do something here based on the different types of actions
    default:
      // If this reducer doesn't recognize the action type, or doesn't
      // care about this specific action, return the existing state unchanged
      return state
  }
}
  • Related