什么是Redux
Redux 是一个用于 JavaScript 应用程序的状态管理库,通常与 React 一起使用。它通过提供一个统一的状态存储来管理应用的状态,使得状态的管理和调试变得更加简单和可预测。redux中文文档、redux英文文档、redux 学习参考文档
Redux 的核心理念是:
- 单一数据源:整个应用的状态保存在一个单一的 store 中,方便进行管理和维护。
- 状态是只读的:唯一改变状态的方法是派发一个 action,这些 action 描述了发生了什么。
- 使用纯函数来修改状态:通过 reducers 来处理 actions,reducers 是纯函数,它接受当前状态和一个 action,返回新的状态。
Redux 提供了一套机制,使得在大型应用中,状态管理变得更加清晰和结构化,非常适合于需要管理复杂状态的应用程序。
可以将 Redux 与 React 或其他视图库一起使用。它体小精悍(只有2kB,包括依赖),却有很强大的插件扩展生态
Redux 核心包做了什么?
Redux 核心包是一个非常小、有意避免主观立场的库。它提供了一些小的 API 原语:
createStore实际创建一个 Redux 存储实例combineReducers将多个 reducer 函数合并成为一个更大的 reducerapplyMiddleware将多个中间件组合成一个 store 增强器compose将多个 store 增强器合并成一个单一的 store 增强器
安装
pnpm add redux react-redux @reduxjs/toolkit
TodoList 案例带你一步步熟悉 redux 的基础用法
"@reduxjs/toolkit": "^2.3.0""antd": "^5.21.1""react": "^18.3.1""react-dom": "^18.3.1""react-redux": "^9.1.2""redux": "^5.0.1""typescript": "^5.6.3"
创建 Redux Slice
// todo.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
interface Todo {
id: number
text: string
}
interface TodoState {
todos: Todo[]
}
const initialState: TodoState = {
todos: [],
}
const todoSlice = createSlice({
name: 'todos',
initialState,
reducers: {
addTodo: (state, action: PayloadAction<string>) => {
const newTodo: Todo = { id: Date.now(), text: action.payload }
state.todos.push(newTodo)
},
removeTodo: (state, action: PayloadAction<number>) => {
state.todos = state.todos.filter((todo) => todo.id !== action.payload)
},
},
})
export const { addTodo, removeTodo } = todoSlice.actions
export default todoSlice.reducer
创建 Redux Store
// store.ts
import { configureStore } from '@reduxjs/toolkit'
import todoReducer from './todoSlice'
const store = configureStore({
reducer: {
todos: todoReducer,
},
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
export default store
设置 Provider
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { Provider } from 'react-redux';
import store from './store';
import App from './App.tsx'
import './index.css'
createRoot(document.getElementById('root')).render(
<StrictMode>
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
)
创建 TodoList 组件
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { addTodo, removeTodo } from './todo';
import { Button, Input, List } from 'antd';
const TodoList: React.FC = () => {
const [inputValue, setInputValue] = useState('');
const dispatch = useDispatch();
const todos = useSelector((state: any) => state.todos.todos);
const handleAddTodo = () => {
if (inputValue.trim()) {
dispatch(addTodo(inputValue));
setInputValue('');
}
};
const handleRemoveTodo = (id: number) => {
dispatch(removeTodo(id));
};
return (
<div style={{ padding: '20px' }}>
<Input
value={inputValue}
onChange={e => setInputValue(e.target.value)}
placeholder="添加新的 todo"
style={{ width: '300px', marginRight: '10px' }}
/>
<Button type="primary" onClick={handleAddTodo}>添加</Button>
<List
style={{ marginTop: '20px' }}
bordered
dataSource={todos}
renderItem={item => (
<List.Item
actions={[<Button type="link" onClick={() => handleRemoveTodo(item.id)}>删除</Button>]}
>
{item.text}
</List.Item>
)}
/>
</div>
);
};
export default TodoList;
在 App 中使用 TodoList
import React from 'react'
import TodoList from './TodoList'
const App: React.FC = () => {
return (
<div>
<h1 style={{ textAlign: 'center' }}>Todo List</h1>
<TodoList />
</div>
)
}
export default App
当然你也可以不使用 @reduxjs/toolkit 的 Redux 应用程序。通过手动创建 reducer、store 和 actions但是不推荐这么做下面会解释以及你也可以对应代码的简洁程度,只需要更改以下几步就是以前你熟悉的用法了尤其是现有老项目(其他的和上面保持一致即可)
创建 Reducer
// todo.ts
interface TodoItem {
id: number
text: string
}
interface TodoState {
todos: TodoItem[]
}
const initialState: TodoState = {
todos: [],
}
// 创建 Reducer
const todoReducer = (state = initialState, action: any) => {
switch (action.type) {
case 'ADD_TODO':
const newTodo: TodoItem = { id: Date.now(), text: action.payload }
return { ...state, todos: [...state.todos, newTodo] }
case 'REMOVE_TODO':
return {
...state,
todos: state.todos.filter((todo) => todo.id !== action.payload),
}
default:
return state
}
}
export default todoReducer
创建 Store
会直接提醒你,但是一样能正常使用,就是不推荐这样使用了(传统用法)
// store.ts
import { createStore } from 'redux';
import todoReducer from './todo';
const store = createStore(todoReducer);
export default store;
创建 TodoList 组件
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Button, Input, List } from 'antd';
interface Todo {
id: number; // 或者 string
text: string;
}
const TodoList: React.FC = () => {
const [inputValue, setInputValue] = useState('');
const dispatch = useDispatch();
const todos = useSelector((state: any) => state.todos);
const handleAddTodo = () => {
if (inputValue.trim()) {
dispatch({ type: 'ADD_TODO', payload: inputValue });
setInputValue('');
}
};
const handleRemoveTodo = (id: number) => {
dispatch({ type: 'REMOVE_TODO', payload: id });
};
return (
<div style={{ padding: '20px' }}>
<Input
value={inputValue}
onChange={e => setInputValue(e.target.value)}
placeholder="添加新的 todo"
style={{ width: '300px', marginRight: '10px' }}
/>
<Button type="primary" onClick={handleAddTodo}>添加</Button>
<List
style={{ marginTop: '20px' }}
bordered
dataSource={todos}
renderItem={(item:Todo) => (
<List.Item
actions={[<Button type="link" onClick={() => handleRemoveTodo(item.id)}>删除</Button>]}
>
{item.text}
</List.Item>
)}
/>
</div>
);
};
export default TodoList;
一样可以达到同样的效果,只是不推荐这样的方式处理了目前~~~~与时俱进吧!!!
为什么 Redux Toolkit 是如今使用 Redux 的方式
推荐使用 Redux Toolkit !!!
什么是 Redux Toolkit?
官方原话:Redux Toolkit (也称为 "RTK" ) 是我们官方推荐的编写 Redux 逻辑的方法。@reduxjs/toolkit 包封装了核心的 redux 包,包含我们认为构建 Redux 应用所必须的 API 方法和常用依赖。 Redux Toolkit 集成了我们建议的最佳实践,简化了大部分 Redux 任务,阻止了常见错误,并让编写 Redux 应用程序变得更容易。
如果今天你要写任何的 Redux 逻辑,你都应该使用 Redux Toolkit 来编写代码
RTK 包括一些实用程序,可以帮助简化许多常见的用例,包括 配置 Redux store、 创建 reducer 函数并使用不可变更新逻辑 和 一次性创建状态的某个"片段"(slice)。
无论你是刚接触 Redux 的新用户正在设计你的第一个项目,还是已有经验的用户想简化一个现有的应用,Redux Toolkit 都能够帮助你写出更好的 Redux 代码。
redux的传统用法或者叫老用法(不使用Redux Toolkit)和现在的新用法(使用Redux Toolkit)对比
1. 安装和配置
-
老用法:
- 需要手动安装 Redux 和 react-redux。
- 创建 Redux store 时,需要明确地使用
createStore和中间件,如applyMiddleware。
import { createStore, applyMiddleware } from 'redux'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; import rootReducer from './reducers'; const store = createStore(rootReducer, applyMiddleware(thunk)); -
新用法(Redux Toolkit) :
- 通过
@reduxjs/toolkit包简化配置,使用configureStore。
import { configureStore } from '@reduxjs/toolkit'; import { Provider } from 'react-redux'; import rootReducer from './reducers'; const store = configureStore({ reducer: rootReducer }); - 通过
2. Reducers 和 Actions
-
老用法:
- 状态管理和动作分离,手动定义动作类型和创建动作生成器。
- 使用
switch语句处理 actions。
const ADD_TODO = 'ADD_TODO'; const addTodo = (text) => ({ type: ADD_TODO, payload: text, }); const todosReducer = (state = [], action) => { switch (action.type) { case ADD_TODO: return [...state, action.payload]; default: return state; } }; -
新用法(Redux Toolkit) :
- 使用
createSlice来自动生成 reducers 和 actions。 - 无需手动创建动作类型和处理逻辑,结构更清晰。
import { createSlice } from '@reduxjs/toolkit'; const todosSlice = createSlice({ name: 'todos', initialState: [], reducers: { addTodo: (state, action) => { state.push(action.payload); }, }, }); export const { addTodo } = todosSlice.actions; export default todosSlice.reducer; - 使用
3. 中间件
-
老用法:
- 手动配置中间件,并使用
applyMiddleware来应用。
- 手动配置中间件,并使用
-
新用法(Redux Toolkit) :
- 默认内置了一些常用的中间件(如
redux-thunk),同时支持自定义中间件的添加。
- 默认内置了一些常用的中间件(如
4. 状态不可变性
-
老用法:
- 开发者需要手动处理状态的不可变性,使用
Object.assign或扩展运算符等。
- 开发者需要手动处理状态的不可变性,使用
-
新用法(Redux Toolkit) :
- 使用 Immer 库,使得状态更新变得简单和直观,开发者可以直接修改状态,内部会处理不可变性。
5. 性能和开发体验
-
老用法:
- 开发流程较为繁琐,需要更多的样板代码。
-
新用法(Redux Toolkit) :
- 简化了 Redux 的配置和使用,降低了入门门槛,提高了开发体验和效率。
- 强调了最佳实践,比如使用
createSlice和configureStore。
总结
Redux Toolkit 通过简化配置、自动生成 reducers 和 actions、支持直接修改状态 (通过 Immer),以及内置中间件等特性,极大地提升了 Redux 的使用体验。因此,对于新项目,推荐使用 Redux Toolkit,而对于已有的老项目,可以逐步迁移到 Redux Toolkit 以获得更好的开发效率。好了,关于redux的用法就介绍到这里吧,剩下的自己琢磨官方api的差异性吧,以实践、思考、总结为主。。。