Home > Mobile >  how to change specific object value instead of overwriting the entire object in redux?
how to change specific object value instead of overwriting the entire object in redux?

Time:04-14

I am working on an app in reactNative where I need to store an object in the redux storage. I want to be able to edit this object and show it in the front end. I have a functional counter which does so, but when I try it with an object it overwrites the entire object to the changed item. How can I edit only that specific item and keep all the other items in the object unaffected?

in this case I mainly want to focus on the setBaseDisarmed action

My actions:

export const increment = () => ({
    type: INCREMENT,
});

export const decrement = () => ({
    type: DECREMENT,
});

export const reset = () => ({
    type: RESET,
});
    
export const setBase = () => ({
    type: SET_BASE,
});

export const setBaseArmed = () => ({
    type: SET_BASE_ARMED,
    id: 1,
    payload: { state: 'armed' },
});
export const setBaseDisarmed = () => ({
    type: SET_BASE_DISARMED,
    id: 1,
    payload: { base: { state: 'disarmed' } },
});

My reducer:

const rootReducer = (state = initialState, action) => {
    switch (action.type) {
        case INCREMENT:
            return {
                ...state,
                counter: state.counter   1,
            };
        case DECREMENT:
            return {
                ...state,
                counter: state.counter - 1,
            };
        case RESET:
            return {
                ...state,
                counter: 0,
            };
        case SET_BASE:
            return {
                ...state,
                id: 1,
                title: 'Title Name',
                state: 'armed',
                created_at: '2022-03-10T12:24:14.000000Z',
                updated_at: '2022-04-11T07:42:34.000000Z',
            };
        case SET_BASE_ARMED:
            return {
                ...state,
                ...action.payload,
            };
        case SET_BASE_DISARMED:
            return {
                ...state,
                ...action.payload,
            };
        case SET_BASE_HOME:
            return {
                ...state,
                state: 'home',
            };
        default:
            return state;
    }
};

Original state:

base: "[{\"id\":1,\"title\":\"Title Name\",\"state\":\"armed\",\"created_at\":\"2022-03-10T12:24:14.000000Z\",\"updated_at\":\"2022-04-11T07:42:34.000000Z\"}]"
counter: "0"

What the setBaseDisarmed does in the redux storage:

base: "{\"state\":\"disarmed\"}"

What I want it to do:

base: "[{\"id\":1,\"title\":\"Title Name\",\"state\":\"disarmed\",\"created_at\":\"2022-03-10T12:24:14.000000Z\",\"updated_at\":\"2022-04-11T07:42:34.000000Z\"}]"
counter: "0"

Id greatly appreciate all tips and help. Thank you for looking into it with me.

CodePudding user response:

Regarding the subject; In your case you are trying to do something like this.

let base = { base: [{id: 1, state: 'armed'}, {id: 2, state: 'disarmed'}] }
let addition = { base: { state: 'disarmed' } }
let newBase = {
   ...base,
   ...addition,
}

// newBase = { base: { state: 'disarmed' } } 

1- You keep a list of objects on Redux.

2- You want to change a specific area of an object in the list.

Step 1: Change this function.

export const setBaseArmed = () => ({
     type: SET_BASE_ARMED,
     payload: { id: 1, state: 'armed' },
});

Step 2: Let's make changes to the reducer.

case SET_BASE_ARMED:
     // We find the targeted item from the list.
     let targetIndex = state.base.findIndex(item => item.id === action.payload.id)

     // We are adding it to the valuable object we sent above.
     let targetObject = {...state.base[targetIndex ], ...action.payload}

     // And we put our updated object back in its place in the list.
     return {
          ...state,
          base: [...state.base.slice(0, targetIndex), targetObject, ...state.base.slice(targetIndex  1)]
     };

We almost do something like this.

let base = [{id: 1, state: 'armed', title: 'Title 1'}, {id: 2, state: 'disarmed', title: 'Title 2'}]
let payload = {id: 1, state: 'disarmed'}


let targetIndex = base.findIndex(item => item.id === payload.id)
let targetObject = {...base[targetIndex], ...payload}
let newBase = [...base.slice(0, targetIndex), targetObject, ...base.slice(targetIndex  1)]

console.log('Default Base:', base)
console.log('New Base:', newBase)

CodePudding user response:

I found the issue together with a colleague. My action only returned the data that I wanted to change instead of returning the entire object, so all the rest data got lost. We're still not sure if this is the best solution but it works. Time for coffee :)

case SET_BASE_ARMED:
    return {
        ...state,
        base: {
            ...state.base,
            state: action.payload.state,
        },
    };

Thank you all for the help

  • Related