skip to Main Content

Here is the code for react reducer. When I update data, the state becomes "undefined".

const intialState = { data: JSON.parse(localStorage.getItem('formData')) || [] };

const formReducer = (state = intialState, action) => {
  switch (action.type) {
    case 'ADD_DATA':
      return { ...state, data: [...state.data, action.payload] };
    case 'UPDATE_DATA':
      {
        console.log('form update data dispatch', action.payload);
        const { id, data } = action.payload;
        const newData = state.data;
        newData.map((item, index) => {
          if (item[0].uid == id) {
            alert(item[0].uid === id);
            newData[index] = data;
            return (state.data = newData);
          }
        });
      }
      break;
    default:
      return state;
  }
};

export default formReducer;

I am using useSelector() to get updated data.

2

Answers


  1. In the UPDATE_DATA case, you are not returning the updated state. This is causing the state to become undefined. The return statement inside the map callback returns the item in the array, and not the state.

    You can rewrite that case like this:

    case 'UPDATE_DATA': {
      const { id, data } = action.payload;
        return {
          ...state,
          data: state.data.map(item => {
            return item.uid === id ? data : item;
          }),
       };
    }
    
    Login or Signup to reply.
  2. There are a couple issues in the UPDATE_DATA reducer case:

    1. The next state value isn’t not returned from the case so upon this action being processed the state will be undefined.
    2. Array.prototype.map returns an array and its callback should be a pure function, it shouldn’t be used to mutate an external reference or the array it is iterating over.
    3. newData is a reference to the current state.data so the reducer case is also mutating the current state instead of returning a new state/array reference.

    A more correct implementation should look like the following:

    case 'UPDATE_DATA':
      const { id, data } = action.payload;
      const newData = state.data.map((item) => { // <-- return new array reference
        if (item[0].uid == id) {
          return data;
        }
        return item;
      });
      return newData; // <-- return next state value
    

    or a bit more succinctly:

    case 'UPDATE_DATA':
      const { id, data } = action.payload;
      return state.data.map((item) => item[0].uid == id ? data : item);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search