Search code examples
javascriptreactjsreact-redux

Redux reducer remove item from nested object state


I'm trying to remove an item from the state in a reducer after a successful api call to delete an item. I think the problem is that I am not removing the deleted item correctly. I tried a number of different ways using filter, map and some, but I can't seem to get the combination correct to remove the deleted record from the state.

Here is the data structure:

"favorites": [
    {
        "folderId": 1,
        "name": "SUV",
        "cars": [
            {
                "uid": 100,
                "carId": 5,
                "year": 2020,
                "make": "Ford",
                "model": "Explorer",
            },
            {
                "uid": 101,
                "carId": 63,
                "year": 2022,
                "make": "Toyota",
                "model": "RAV-4",
            },
            {
                "uid": 102,
                "carId": 165,
                "year": 2018,
                "make": "Honda",
                "model": "Pilot",
            },
        ]
    },
    {
        "folderId": 2,
        "name": "Trucks",
        "cars": [
            {
                "uid": 103,
                "carId": 75,
                "year": 2024,
                "make": "Ford",
                "model": "F-150",
            },
            {
                "uid": 104,
                "carId": 34,
                "year": 2019,
                "make": "Dodge",
                "model": "RAM",
            }
        ]
    }
]

And the reducer:

const exampleReducer = (state = initialState, action: AnyAction) => {
    const { type, payload } = action;

    switch (type) {
        case types.DELETE_CAR_FROM_USER_FAVORITES_FOLDER_SUCCESS:
            return { ...state, favorites: state.favorites?.filter(folder => folder.cars.some(car=> car.uid !== payload)) };
    }
};
        
        

Solution

  • map over the favourites array and for each folder return a new object containing the old folder data along with the filtered car data.

    (Also: make sure the type of payload matches the type of uid in your data.)

    const data = {favorites:[{folderId:1,name:"SUV",cars:[{uid:100,carId:5,year:2020,make:"Ford",model:"Explorer"},{uid:101,carId:63,year:2022,make:"Toyota",model:"RAV-4"},{uid:102,carId:165,year:2018,make:"Honda",model:"Pilot"}]},{folderId:2,name:"Trucks",cars:[{uid:103,carId:75,year:2024,make:"Ford",model:"F-150"},{uid:104,carId:34,year:2019,make:"Dodge",model:"RAM"}]}]};
    
    const exampleReducer = (state = initialState, action) => {
      const { type, payload } = action;
      switch (type) {
        case 'delete': {
          return {
            ...state,
            favorites: state.favorites.map(folder => {
              return {
                ...folder,
                cars: folder.cars.filter(car => car.uid !== payload)
              }
            })
          };
        }
        default: return state;
      }
    };
            
    const out = exampleReducer(data, { type: 'delete', payload: 104 });
    console.log(out);