Search code examples
reduxreact-reduxredux-toolkit

Changing state with a condition in Redux Slice


I have a problem with changing state with condition in Redux Slice.

I have a simple Slice, where I need edit value in state and that's just in case when the payload is same object which is already in the store.

Example of my payload:

{
unix: 1667500191,
type: "lunch",
order: 2,
value: "gulash"
}

Inputs that have a payload value are actively changed by the administrator. Therefore, every time I change the input, I capture the values with the help of a reducer and try to check if the given input is already in the store and if so I want to change its value. If it's not in the store, I just want to add it.

import { createSlice } from "@reduxjs/toolkit";

const initialState = [];

export const menuSlice = createSlice({
  name: "menu",
  initialState,
  reducers: {
    add: (state, action) => {
      const { order, type, value } = action.payload;

      let newState = [...state, action.payload];

      newState?.map((item, i) => {
        if (item.type === type && item.order === order) {
          newState[i].value = value;
        }
      });

      return newState;
    },
  },
});

export const { add, remove } = menuSlice.actions;

export default menuSlice.reducer;

Can someone please help me? This seems to be broken, but I can't figure out why.

Thanks


Solution

  • This sort of comparison check is easier if your items have a unique id. Based on your current code, it seems like an item is a duplicate if it has the same type and order. It may help with readability if we move that check into a utility function.

    const isSameItem = (a, b) => a.order === b.order && a.type === b.type;
    

    Therefore, every time I change the input, I capture the values with the help of a reducer and try to check if the given input is already in the store and if so I want to change its value. If it's not in the store, I just want to add it.

    We can make use of the array .find() or .findIndex() functions to get the existing item. If there is no existing item then we just .push() it to the end of the array.

    addOrUpdate: (state, action) => {
      // see if it already exists
      const extistingIndex = state.findIndex(item => isSameItem(item, action.payload));
      // add new items  
      if (existingIndex === -1) {
        state.push(action.payload);
      }
      // replace existing items
      else {
        state[existingIndex] = action.payload;
      }
    }