Slice
Content
Slices as well as AsyncThunks are stored together for better readability and remove need to have additional imports.
Creation
Slices are created the same way as described in documentation.
E.g. systemSlice.ts:
export const {reducer: SystemReducer} = createSlice({
name: "system",
initialState: SystemInitialState,
reducers: {
setOnboarding: onboardingHandler,
},
extraReducers: (builder) => {
builder.addCase(REHYDRATE, rehydrate);
},
});
In extraReducers don't forget to add the REHYDRATE case to set properly store after rehydration:
function rehydrate(state: SystemState, rehydrateParams: RehydrateAppAction) {
return newState(rehydrateParams.payload?.system || state, {isOnboardingVisited: rehydrateParams.payload != null});
}
Adding reducer to RootReducer
To see and use our reducer, first it has to be added into RootReducer, which is constructed using combineReducers
and can be found in src/core/store/rootReducer.ts.
E.g. of adding SystemReducer into RootReducer:
export const rootReducer = combineReducers({
system: SystemReducer,
});
Parameter should be the same as name which was used in createSlice
Case handlers
Case handlers as you could see in example of the rehydrate case should be handled as a separate function for better readability.
Return newState
Even though Immer is used under the hood of the toolkit, it's still better to return newState
rather than change properties directly without returning anything.
function rehydrate(state: SystemState, rehydrateParams: RehydrateAppAction) {
return newState(rehydrateParams.payload?.system || state, {isOnboardingVisited: rehydrateParams.payload != null});
}