Reputation: 185
I using reselect and I have some problem about select state from my store.
My redux store look like:
store = {
boxs: {
space: 'large',
view: 'card',
options: {
option01: { id: '01', name: 'Option1', value: true },
option02: { id: '02', name: 'Option2', value: false },
option03: { id: '02', name: 'Option3', value: false },
},
},
};
Here is my selector.js
const getSpace = createSelector(
(state) => state.boxs.space,
(space) => space
);
const getSpaceAndView = createSelector(
(state) => state.boxs,
(boxs) => ({
space: boxs.space,
view: boxs.view,
})
);
const getOptions = createSelector(
(state) => state.boxs,
(boxs) => ({ ...boxs.options })
);
// I use this but when options change value, Component3 not re-render, why ???
/*const getPreferences = createSelector(
(state) => state.boxs,
(boxs) => boxs.options
);*/
My reducer
reducers = (state = initState, action) => {
switch (action.type) {
...
case 'CHANGE_OPTIONS':
const { key, val } = action; // key = 'option01' | 'option02' | 'option03', value = true || false
const newState = { ...state };
newState.boxs.options[key].value = val;
return newState;
default:
return state;
}
}
I have 3 components. Component1 use state.boxs.space
. Component2 use state.boxs.view
and state.boxs.space
. Component3 use state.boxs.options
. When Component3 change state.boxs.options
value (dispatch action CHANGE_OPTIONS in my reducer). Component2 and Component1 will re-render. How to stop re-render ? Thank for your help.
Upvotes: 0
Views: 308
Reputation: 202618
I use this but when options change value, Component3 not re-render, why ???
/*const getPreferences = createSelector( (state) => state.boxs, (boxs) => boxs.options );*/
The reducer should be a pure function. You look to be mutating state objects. You should shallow copy all the data you'll be updating.
reducers = (state = initState, action) => {
switch (action.type) {
...
case 'CHANGE_OPTIONS':
const { key, val } = action; // key = 'option01' | 'option02' | 'option03', value = true || false
return {
...state,
boxs: {
...state.boxs,
options: {
...state.boxs.options,
[key]: {
...state.boxs.options[key],
value: val,
},
},
},
};
default:
return state;
}
}
A small improvement to be more DRY and utilize memoization is to create an initial input selector to select your state.boxs
object to be used as input to the other selectors.
const boxsSelector = state => state.boxs;
const getSpace = createSelector(
[boxsSelector],
boxs => boxs.space,
);
const getSpaceAndView = createSelector(
[boxsSelector],
boxs => ({
space: boxs.space,
view: boxs.view,
})
);
const getOptions = createSelector(
[boxsSelector],
boxs => boxs.options,
);
Upvotes: 1