/** * Redux Toolkit Demo Page * Demonstrates Redux patterns with Redux Toolkit */ import { useState } from 'react'; import { Link } from 'react-router-dom'; import { useAppDispatch, useAppSelector } from '@/store'; import { selectTodosFilter, selectTodoStats, selectFilteredTodos, setFilter, } from '@/store/slices/todosSlice'; import { selectTheme, selectResolvedTheme, selectSidebarCollapsed, setTheme, toggleSidebar, addNotification, removeNotification, selectNotifications, } from '@/store/slices/uiSlice'; export default function ReduxDemo() { const dispatch = useAppDispatch(); // Todos slice selectors const filter = useAppSelector(selectTodosFilter); const stats = useAppSelector(selectTodoStats); const filteredTodos = useAppSelector(selectFilteredTodos); // UI slice selectors const theme = useAppSelector(selectTheme); const resolvedTheme = useAppSelector(selectResolvedTheme); const sidebarCollapsed = useAppSelector(selectSidebarCollapsed); const notifications = useAppSelector(selectNotifications); const [notificationText, setNotificationText] = useState(''); const handleAddNotification = () => { if (!notificationText.trim()) return; dispatch(addNotification({ type: 'info', title: 'Notification', message: notificationText, })); setNotificationText(''); }; return (
Global state management with slices, thunks, and selectors.
{`import { createSlice, PayloadAction } from '@reduxjs/toolkit';
const uiSlice = createSlice({
name: 'ui',
initialState: {
theme: 'system' as 'light' | 'dark' | 'system',
sidebarCollapsed: false,
},
reducers: {
setTheme: (state, action: PayloadAction<'light' | 'dark' | 'system'>) => {
state.theme = action.payload;
},
toggleSidebar: (state) => {
state.sidebarCollapsed = !state.sidebarCollapsed;
},
},
});
export const { setTheme, toggleSidebar } = uiSlice.actions;`}
{`import { createAsyncThunk } from '@reduxjs/toolkit';
export const fetchTodos = createAsyncThunk(
'todos/fetchTodos',
async (_, { rejectWithValue }) => {
try {
const { data, error } = await supabase
.from('todos')
.select('*');
if (error) throw error;
return data;
} catch (error) {
return rejectWithValue(error.message);
}
}
);`}
{`// Simple selector
export const selectTheme = (state: RootState) => state.ui.theme;
// Memoized selector with reselect
export const selectFilteredTodos = createSelector(
[selectTodos, selectTodosFilter],
(todos, filter) => {
switch (filter) {
case 'active': return todos.filter(t => !t.completed);
case 'completed': return todos.filter(t => t.completed);
default: return todos;
}
}
);`}
{`import { useAppDispatch, useAppSelector } from '@/store';
function MyComponent() {
const dispatch = useAppDispatch();
const theme = useAppSelector(selectTheme);
return (
);
}`}