State Management
When to Use Slices vs RTK Query
State Type
Tool
Examples
Creating a Basic Slice
// src/features/ui/ui.slice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import type { RootState } from '@/app/store';
interface UIState {
sidebarOpen: boolean;
modalOpen: boolean;
viewMode: 'grid' | 'list';
theme: 'light' | 'dark';
}
const initialState: UIState = {
sidebarOpen: true,
modalOpen: false,
viewMode: 'grid',
theme: 'light',
};
const uiSlice = createSlice({
name: 'ui',
initialState,
reducers: {
// Boolean toggles
sidebarToggled(state) {
state.sidebarOpen = !state.sidebarOpen;
},
// Set specific value
modalOpened(state) {
state.modalOpen = true;
},
modalClosed(state) {
state.modalOpen = false;
},
// Payload actions
viewModeChanged(state, action: PayloadAction<'grid' | 'list'>) {
state.viewMode = action.payload;
},
themeChanged(state, action: PayloadAction<'light' | 'dark'>) {
state.theme = action.payload;
},
// Multiple properties
uiReset() {
return initialState;
},
},
});
// Export actions
export const {
sidebarToggled,
modalOpened,
modalClosed,
viewModeChanged,
themeChanged,
uiReset,
} = uiSlice.actions;
// Export reducer
export default uiSlice.reducer;
// Export selectors
export const selectSidebarOpen = (state: RootState) => state.ui.sidebarOpen;
export const selectModalOpen = (state: RootState) => state.ui.modalOpen;
export const selectViewMode = (state: RootState) => state.ui.viewMode;
export const selectTheme = (state: RootState) => state.ui.theme;Using Entity Adapters
Entity Adapter Methods
State Mutations
Generated Selectors
Complex State Example
Memoized Selectors
Async Logic with Extra Reducers
Best Practices
1. Keep State Minimal
2. Use Immer-Friendly Mutations
3. Organize Reducers Logically
4. Type Actions Properly
Testing Slices
Next Steps
Last updated