Reputation: 47
My redux state has a SessionList which is an array of SessionObjects, and each SessionObject has an array of HandObjects.
I use state to update individual SessionObjects by adding new HandObjects, however I want to update the redux store with my updated SessionObject (immutably, if possible).
the index of the SessionObject within SessionList is action.payload.Id (I think? i will show my SessionObject constructor)
**Adding Sessions works just fine, and I only update a Session with the session already in the store
I have tried every link that I can find, but my code is just different enough that I can't seem to update my SessionList correctly.
my reducer, with the initial state store.js (where my reducers are)
const initialState = {
SessionList: [],
}
...
case "UPDATE_SESSION":
//action.payload is a SessionObject
//action.payload.Id is the Id that i want to update
// i want to set SessionList[action.payload.Id] = action.payload
state = {
...state,
SessionList : state.SessionList.map((item, index) => {
if (index != action.payload.id) {
return item
}
return action.payload
//This code doesn't visibly do anything that I can find
})
// *******FIRST TRY*******
// ...state,
// SessionList: {
// ...state.SessionList,
// SessionList[action.payload.id] : action.payload
//syntax error, but basically what i want to do
// }
// }
// ***********************
};
break;
SessionObject constructor Session.js
export function SessionObject(_id, _name, _hands) {
this.id = _id, //int
this.name = _name, //string
this.HandList = _hands //array of HandObject objects
}
var defaultSession = new SessionObject(0, "default", []);
*in case i am doing this wrong, I call (Session.js)
this.props.navigation.state.params.updateMethod(this.state.Session); //update store
from a stack-navigator child component.
then in the parent component,
I call
(Home.js)
UpdateSession = (session) => {
this.props.updateSession(session);
};
With my dispatcher looking like: (Home.js)
updateSession: (session) => {
dispatch({
type: "UPDATE_SESSION",
payload: session
});
}
From testing, I am somewhat sure my reducer is getting called correctly.
I want to replace the SessionObject with action.payload in the correct index of the SessionList.
EDIT *
Session.js
addItem = () => {
this.setState((state, props) => ({
Session : {
...state,
HandList: [...state.Session.HandList, new HandObject(state.HandCount)]
},
HandCount : state.HandCount + 1,
}));
this.props.navigation.state.params.updateMethod(this.state.Session); //update store
};
The state in Session.js is a SessionObject
Upvotes: 1
Views: 1148
Reputation: 6104
To achieve a result of SessionList[action.payload.Id]
, you need to initialise SessionList
as an object and not an array. Then you can update accordingly.
const initialState = {
SessionList: {},
}
case "UPDATE_SESSION":
state = {
...state,
SessionList: Object.keys(state.SessionList).reduce((acc, id) => {
if (id === action.payload.Id) {
acc[id] = action.payload;
} else {
acc[id] = state.SessionList[id];
}
return acc;
}, {});
};
Update
As requested here, following are the add, update, replace and delete handlers without changing SessionList
to an object.
const initialState = {
SessionList: [],
}
Note: action.payload
(wherever used) is a session object.
Add
state = {
...state,
SessionList: [...state.SessionList, action.payload];
};
Update
state = {
...state,
SessionList: state.SessionList.map((session) => {
if (session.Id === action.payload.Id) {
return Object.assign({}, session, action.payload);
}
return session;
})
};
Replace
state = {
...state,
SessionList: state.SessionList.map((session) => {
if (session.Id === action.payload.Id) {
return action.payload;
}
return session;
})
};
Delete
state = {
...state,
SessionList: state.SessionList.filter((session) => session.Id !== action.payload.Id)
};
Upvotes: 4