Reputation: 83
I have a react application in typescript and I am using redux to structure the project. I have currently have 2 reducers, one to get a list of items from the backend and the other to perform operations on the user model. Below are my two reducers and I am using combinedReducers when creating the redux store.
UserReducer:
export const userReducer: Reducer<IUserState, UserActions> = (
state = initialUserState,
action
) => {
switch(action.type) {
case UserActionTypes.GET_CURRENT_USER: {
return {
...state,
currentUser: action.currentUser
}
}
case UserActionTypes.SIGN_IN_USER: {
return {
...state,
currentUser: action.currentUser
}
}
default:
return initialUserState
}
}
ListReducer:
export const listReducer: Reducer<IListState, ListActions> = (
state = initialListState,
action
) => {
switch(action.type) {
case ListActionTypes.GET_ALL: {
return {
...state,
items: actions.items
}
}
case ListActionTypes.FILTER_LIST: {
return {
...state,
items: action.items
}
}
default:
return initialListState
}
}
combinedReducer
const rootReducer = combineReducers<IAppState>({
listState: listReducer,
userState: userReducer
})
The problem I am having is that when I dispatch a list action the action will be performed correctly in the list reducer but the action is also sent to the user reducer. Since the user reducer doesn't account for the list action the initial state is returned. If I only call the GET_CURRENT_USER action I get the user's information but once I call the GET_ALL action the user information is reset to null.
Upvotes: 0
Views: 47
Reputation: 9357
You're returning the initial state in the default:
statement. Try this:
export const userReducer: Reducer<IUserState, UserActions> = (
state = initialUserState,
action
) => {
switch(action.type) {
case UserActionTypes.GET_CURRENT_USER: {
return {
...state,
currentUser: action.currentUser
}
}
case UserActionTypes.SIGN_IN_USER: {
return {
...state,
currentUser: action.currentUser
}
}
default:
return {...state}; // <= instead of initialUserState
}
}
Do the same with the other reducer.
As an advice, try using immerjs
to avoid mutating your objects. When you have nested objects, using the spread operator deep in the object becomes quite hard to read and error-prone (it's easy to inadvertently mutate your object).
By using immerjs
your code becomes:
import produce from "immer";
...
export const userReducer: Reducer<IUserState, UserActions> = (
state = initialUserState,
action
) => {
switch(action.type) {
case UserActionTypes.SIGN_IN_USER:
case UserActionTypes.GET_CURRENT_USER: {
return produce(state, draftState => {
draftState.currentUser: action.currentUser
});
}
default:
return produce(state, draftState => {});
}
}
Upvotes: 1