I'm trying to create a MemoizedSelector with createSelector
. I want to use another MemoizedSelector as it's input. But after root state is changed this selector doesn't recalculate new selected value.
E.g. we have a state:
const initialState: RootState = {
user: {
name: {
first: 'John',
last: 'Doe',
},
},
};
and a chain of reducers:
const userSelector = (state: RootState) => state.user;
const nameSelector : MemoizedSelector<RootState, UserName> = createSelector(
userSelector,
(user: User) => user.name
);
const lastNameSelector : MemoizedSelector<RootState, string> = createSelector(
nameSelector,
(userName: UserName) => userName.last
);
So when we select the first name and change it in a reducer:
this.store$.select(lastNameSelector).subscribe(it => console.log(it));
this.store$.dispatch({type:'CHANGE_LAST_NAME', payload: 'Brown'});
We can't see "Brown" in the log.
I can make it work with clean function:
const lastNameSelector = (state: RootState) => state.user.name.last;
but I want to take advantage of memoization, and don't recalculate user's last name when any other state param is changed. What can I do to make it work?
Example app: https://github.com/vadim-shb/ngrx-issue
UPDATE:
The issue was in the reducer:
export function userReducer(state: UserData = initialState, action: any) {
if (action.type === 'CHANGE_LAST_NAME') {
let result = {
...state
};
result.name.last = action.payload;
return result;
}
return state;
}
in your reducer, try this:
if (action.type === 'CHANGE_LAST_NAME') {
let result = {
...state,
name: {
...state.name,
last: action.payload
}
}
return result;
}