通过 Todo List App 学习 Redux Toolkit
Redux Toolkit is the official, opinionated, batteries-include toolset for efficient Redux development
Introduction
Redux is a state management for frontend lib, like React. It is complex and not easier to use and understand. So the Redux Toolkit is out. Less code, less api, but more powerful. In this tutorial, I do not introduce what is redux, I will explain how to use it in a little app. I prefer to use Redux Toolkit in your project. I also show how to use typescript with redux.
The UI
The UI such like this below. Not focus on css, very simple.
- click the "play" can change it to done
- click the doing or done button can change the status to filter the todo list
Create Project
Now we should use Create React App tool to init our project.
npx create-react-app todoList --template typescript
Create the static page
- create components
- change
App.tsx
import TodoList from './components/TodoList/TodoList';
import Filter from './components/Filter/Filter';
import SearchPanel from './components/SearchPanel/SearchPanel';
import './App.css';
function App() {
return (
<div className="main">
<SearchPanel />
<div className="todoList">
<TodoList />
</div>
<Filter />
</div>
);
}
export default App;
Use Redux Toolkit
Install Redux Toolkit
Also need to install react-redux
npm install @reduxjs/toolkit react-redux
Create Store
Store is where the state is stored globally
Create store file
config store
use configureStore api to create store. Now we create an empty store
import { configureStore } from '@reduxjs/toolkit';
export const store = configureStore({
reducer: {}
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
Provide redux store to react
change index.tsx
file
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { store } from './app/store';
import { Provider } from 'react-redux';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
Create Redux State Slice
Add two slice file named filter
and todoList
/src/features/filter/filterSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
export type StatusType = 'all' | 'done' | 'doing';
interface FilterProps {
status: StatusType;
}
const initialState: FilterProps = {
status: 'all'
};
export const filterSlice = createSlice({
name: 'filter',
initialState,
reducers: {
changeStatus: (state, action: PayloadAction<StatusType>) => {
state.status = action.payload;
}
}
});
export const { changeStatus } = filterSlice.actions;
export default filterSlice.reducer;
/src/features/todoList/todoListSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
interface TodoListProps {
allTodo: TodoItemProps[];
}
export interface TodoItemProps {
id: string;
name: string;
isComplete: boolean;
}
const initialState: TodoListProps = {
allTodo: [{ id: '0', name: 'play', isComplete: false }]
};
export const todoListSlice = createSlice({
name: 'todoList',
initialState,
reducers: {
addItem: (state, action: PayloadAction<string>) => {
const item: TodoItemProps = {
id: (Math.random() * 1000000).toFixed(0),
name: action.payload,
isComplete: false
};
state.allTodo.push(item);
},
changeItemStatus: (state, action: PayloadAction<string>) => {
const item = state.allTodo.find((item) => item.id === action.payload);
if (item) {
item.isComplete = !item.isComplete;
}
}
}
});
export const { addItem, changeItemStatus } = todoListSlice.actions;
export default todoListSlice.reducer;
Create a slice require a string name identify slice, need a initialState, and one or more reducer functions to define how the state can be updated
then export the action creators and reducer for the whole slice
Add Slice Reducers to the Store
Just import all reducers and add to the store
import { configureStore } from '@reduxjs/toolkit'
import todoListReducer from '../features/todoList/todoListSlice'
import filterReducer from '../features/filter/filterSlice'
export const store = configureStore({
reducer: {
++ todoList: todoListReducer,
++ filter: filterReducer,
},
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
Use The State
Use State
We can use useSelector
to get the state
import { useSelector } from 'react-redux';
import { RootState } from '../../app/store';
const filter = useSelector((state: RootState) => state.filter.status);
Change State
import { useDispatch } from 'react-redux';
import { changeStatus } from '../../features/filter/filterSlice';
const dispatch = useDispatch();
dispatch(changeStatus(status));
For now we can get state and can change state, the todoList slice is same, you can clone this github repository to get all code
Final Output

Conclusion
When you need to use Redux in your project, I prefer Redux Toolkit than regular redux way. This way less code, less api, easier to understand. And it contain redux-thunk, I will update this part.
That’s all, Thank you.