Reputation: 1341
I'm new to Redux so please bear with me. I am wondering if something like the following is possible and/or optimal and if so, how do you update the nested object values in the reducer?
const initialState = {
banner: {
backgroundColor: 'black',
text: 'Some Title',
textColor: 'white',
image: null
},
nav: {
mainOpen: false,
authOpen: false,
}
...
}
And then in a reducer something like this does not seem to work...
export default function reducer(state = initialState, action = {}) {
const {type, data} = action;
switch (type) {
case SET_BANNER_TEXT:
return {
...state,
banner.text: data //<-- ****THIS FAILS WITH UNEXPECTED TOKEN!!!****
}
...
}
Or is it better to to have a 'banner' reducer, a 'nav' reducer and so on??
TIA!
Upvotes: 0
Views: 327
Reputation: 1309
Since you're updating a key of an object, try using this to update the key
const state = {
...initialState,
banner: {
...initialState.banner, // extend
text: 'newText'
}
}
which translates to
var state = _extends({}, initialState, {
banner: _extends({}, initialState.banner, {
text: 'newText'
})
});
in ES5
check this jsbin
edit: as stated in the comment below, it will overwrite the whole banner object if the code is used above. You can try the other answer in this thread using the Object.assign()
and clone the banner
object. If you still want to use spread operators, I updated my answer.
I think it is also better to have specific reducers for deeply nested state.And I will write it something like this
export function rootReducer(state = initialState, action) {
switch (action.type) {
case SET_BANNER_TEXT:
case SET_BANNER_BG:
return Object.assign({}, state,
{
banner: bannerReducer(state.banner, action)
}
);
// ...
default:
return state;
}
}
function bannerReducer(state, action) {
switch (action.type) {
case SET_BANNER_TEXT:
return Object.assign({}, state, {text: action.payload});
case SET_BANNER_BG:
return Object.assign({}, state, {backgroundColor: action.payload});
// ...
default:
return state;
}
}
Upvotes: 1
Reputation: 379
I'm a bit new to redux too, so I can't speak too much to 'best practice'. I would lean towards a new reducer personally, since you have have specific actions like SET_BANNER_TEXT
(color, img, etc?) that modify a specific portion of your state tree and nothing else. Making your reducers simple by breaking them apart, (even if there are a lot of them), will make things easier to trace down the road.
Syntactically you could achieve what you're trying to do with something like:
export default function reducer(state = initialState, action = {}) {
const {type, data} = action;
switch (type) {
case SET_BANNER_TEXT:
const newBannerState = Object.assign({}, state.banner, {text: data});
return Object.assign({}, state, {banner: newBannerState});
}
Upvotes: 2