Home > other >  Redux - InitialState - array vs object issue
Redux - InitialState - array vs object issue

Time:10-12

I have a problem with my InitialState with an error hidden somewhere. When I keep my InitialState in an array all these things work (* NOTES.TS is an array of objects). But when I try to make it an object, it doesn't seem to work at all. Can't find where's the issue...

const INITIAL_STATE: any[] = [...NOTES];

export const reducer = (state: any[] = INITIAL_STATE, action: any) => {
  switch (action.type) {
    case UPDATE_NOTE: {
      return state.map((note) =>
        note.id === action.payload.id
          ? {
              ...note,
              status: "ARCHIVED",
            }
          : note
      );
    }

    case CREATE_NOTE: {
      return state.concat([
        {
          description: 'jj',
          id: 12,
          status: NOTE_STATUS.ACTIVE,
          timestamp: CURRENT_DATE,
          images: [],
          username: "John Smith",
        },
      ]);
    }

    default:
      return state;
  }
};

export default reducer;

and my filters in the selectors:

const globalSelector = (state: any) => state.notes;

export const selectCurrentNotes = createSelector(globalSelector, (notes) => {
  return notes.filter((p: any) => p.status === NOTE_STATUS.ACTIVE);
});

But I needed to add more stuff to the InitialState, so I decided to make it an object and literally nothing works. Why?

const INITIAL_STATE: any = {
     all: [...NOTES],
     description: '',
     images: []
};

export const reducer = (state: any = INITIAL_STATE, action: any) => {
  switch (action.type) {
    case UPDATE_NOTE: {
      return state.all.map((note) =>
        note.id === action.payload.id
          ? {
              ...note,
              status: "ARCHIVED",
            }
          : note
      );
    }

    case CREATE_NOTE: {
      return state.all.concat([
        {
          description: 'jj',
          id: 12,
          status: NOTE_STATUS.ACTIVE,
          timestamp: CURRENT_DATE,
          images: [],
          username: "John Smith",
        },
      ]);
    }

    default:
      return state;
  }
};

export default reducer;

and my filters in the selectors:

const globalSelector = (state: any) => state.notes.all;

export const selectCurrentNotes = createSelector(globalSelector, (notes) => {
  return notes.filter((p: any) => p.status === NOTE_STATUS.ACTIVE);
});

EDIT: First error concerns filters:

TypeError: undefined is not an object (evaluating 'notes.filter')

EDIT 2: notes in filters are the name of the reducer, stored with the other ones in the global store.

const reducers = combineReducers({ favourites, notes, notifications, });

CodePudding user response:

Because in your reducer you do return state.all.map which will overwrite the object state with the mapped array of notes.

You need to do

export const reducer = (state: any = INITIAL_STATE, action: any) => {
  switch (action.type) {
    case UPDATE_NOTE: {
      return {
        ...state,
        all: state.all.map((note) =>
        note.id === action.payload.id
          ? {
              ...note,
              status: "ARCHIVED",
            }
          : note
         )};
    }

    case CREATE_NOTE: {
      return {
        ...state,
        all: state.all.concat([
        {
          description: 'jj',
          id: 12,
          status: NOTE_STATUS.ACTIVE,
          timestamp: CURRENT_DATE,
          images: [],
          username: "John Smith",
        },
      ])
      };
    }

    default:
      return state;
  }
};

CodePudding user response:

Your reducer is returning different types which I don't think is what you want. For example:

return state.all.map((note) =>
    note.id === action.payload.id
      ? {
          ...note,
          status: "ARCHIVED",
        }
      : note
  );

This is just returning the updated all property of your state. Instead, you probably want:

const newAll = state.all.map((note) =>
  note.id === action.payload.id
    ? {
        ...note,
        status: "ARCHIVED",
      }
    : note
);

return {...state, all: newAll };

You'll need to fix this for all parts of your reducer to make sure you're returning the full state each time.

  • Related