Search code examples
typescriptreduxredux-toolkitredux-reducers

Redux toolkit not updating array of array object


I'm trying to update an object that is nested in an array of arrays.

state = [[{away: "Southampton "
awayTeamScore: null
date: "Sat, October 30th 2021"
dateNative: "2021-10-30T14:00:00Z"
home: "Watford "
homeTeamScore: null
matchId: 327264
matchday: 10
score: "null - null"
time: "16:00"
winner: null}, {..etc}], [{..etc}]]

I am passing my payload which looks like this:

{matchId: 327264
score: 1
team: "awayTeamScore"}

But my redux state does not update, I tried to follow the official docs regaring immer etc.

My attempt reducer, using createSlice:

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

export const predictFormSlice: any = createSlice({
    name: "predictForm",
    initialState: [],
    reducers: {
        SAVE_FIXTURES: (state: any, action) => {
            state.push(action.payload);
        },
        UPDATE_PREDICTIONS: (state: any, action) => {
            state = state[0].map((element: any[]) => {
                let game = element.find((game: { matchId: any }) => game.matchId === action.payload.matchId);

                if (game) {
                    game = action.payload;
                }
            });
        },
    },
});

export const { SAVE_FIXTURES, UPDATE_PREDICTIONS } = predictFormSlice.actions;

export default predictFormSlice.reducer;

It would be nice to just update the key for the awayTeamScore and homeTeamScore by using the matchId, inside the reducer. My action is sending the payload successfully to the UPDATE_PREDICTION reducer, just not updating the state, I was just trying to completely replace the object first before just focusing on certain keys.


Solution

  • Several things here:

    • you are confusing modifying an object and reassigning a variable. You can do variableName.foo = 5 and it will change the property foo of variableName to 5. But if instead you would do let foo = variableName.foo; foo = 5, you would assign the value 5 to the variable foo, but there would not be a connection to variableName any more - variableName would not change. You are doing this with both state and game here: you reassign both variables, but you "change" nothing.
    • you create a full new array with .map - you don't need to do that in an immer reducer.

    This would go about this in a "object-modifying" approach instead of reassigning things.

            UPDATE_PREDICTIONS: (state: any, action) => {
                for (const element of state[0]) {
                    let idx = element.findIndex((game: { matchId: any }) => game.matchId === action.payload.matchId);
    
                    if (idx >= 0) {
                        element[idx] = action.payload;
                    }
                };
            },