08. Redux 核心概念一、5W1H 概述维度内容WhatRedux 的核心三要素Store、Action、ReducerWhy可预测的状态管理适合大型应用When大型复杂应用、团队协作项目Where全局 store 配置Who需要成熟状态管理方案的开发者HowStore 存储状态Action 描述变化Reducer 执行变化二、What - 什么是 ReduxRedux 是一个可预测的 JavaScript 状态容器用于管理应用的全局状态。核心三要素┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Action │ ──▶ │ Reducer │ ──▶ │ Store │ │ (描述变化) │ │ (执行变化) │ │ (存储状态) │ └─────────────┘ └─────────────┘ └─────────────┘ ▲ │ └────────────────────────────────────────┘ dispatch(action)三大原则原则说明单一数据源整个应用的状态存在一个 Store 中State 只读唯一改变状态的方式是触发 Action纯函数修改使用纯函数 Reducer 来修改状态三、Why - 为什么需要 Redux3.1 可预测性状态变化可追踪、可调试。3.2 集中管理全局状态集中在一个 Store 中便于管理。3.3 时间旅行调试可以回溯到任意历史状态。3.4 生态丰富有大量中间件和工具支持。四、When - 何时使用 Redux场景推荐程度说明大型复杂应用✅ 推荐状态多、交互复杂团队协作项目✅ 推荐规范统一需要时间旅行调试✅ 推荐调试复杂 bug中小型应用❌ 不推荐过于重量级简单状态管理❌ 不推荐使用 Context 或 Zustand五、Where - 在哪里使用src/ ├── store/ │ ├── index.js # Store 配置 │ ├── actions.js # Action 定义 │ └── reducers.js # Reducer 定义 └── components/ └── Component.jsx # 连接 Redux六、Who - 谁需要使用大型复杂应用的开发者或需要调试能力的团队。七、How - 如何使用 Redux7.1 安装npminstallredux react-redux7.2 Action 定义// actions.js // Action 类型常量 export const INCREMENT INCREMENT; export const DECREMENT DECREMENT; export const SET_USER SET_USER; export const ADD_TODO ADD_TODO; // Action Creator export const increment () ({ type: INCREMENT }); export const decrement () ({ type: DECREMENT }); export const setUser (user) ({ type: SET_USER, payload: user }); export const addTodo (text) ({ type: ADD_TODO, payload: { id: Date.now(), text, completed: false } });7.3 Reducer 定义// reducers.js import { combineReducers } from redux; import { INCREMENT, DECREMENT, SET_USER, ADD_TODO } from ./actions; // 计数器 Reducer const counterReducer (state 0, action) { switch (action.type) { case INCREMENT: return state 1; case DECREMENT: return state - 1; default: return state; } }; // 用户 Reducer const userReducer (state null, action) { switch (action.type) { case SET_USER: return action.payload; default: return state; } }; // Todo Reducer const todoReducer (state [], action) { switch (action.type) { case ADD_TODO: return [...state, action.payload]; default: return state; } }; // 组合 Reducer export const rootReducer combineReducers({ count: counterReducer, user: userReducer, todos: todoReducer });7.4 Store 创建// store/index.js import { createStore } from redux; import { rootReducer } from ./reducers; // 创建 Store const store createStore(rootReducer); export default store;7.5 Provider 配置// App.jsx import { Provider } from react-redux; import store from ./store; import Counter from ./components/Counter; function App() { return ( Provider store{store} Counter / /Provider ); }7.6 组件中使用// components/Counter.jsx import { useSelector, useDispatch } from react-redux; import { increment, decrement } from ../store/actions; function Counter() { // 读取状态 const count useSelector(state state.count); const user useSelector(state state.user); const todos useSelector(state state.todos); // 获取 dispatch const dispatch useDispatch(); return ( div p计数: {count}/p button onClick{() dispatch(increment())}/button button onClick{() dispatch(decrement())}-/button /div ); }7.7 完整示例Todo 应用// actions.js export const ADD_TODO ADD_TODO; export const TOGGLE_TODO TOGGLE_TODO; export const DELETE_TODO DELETE_TODO; export const addTodo (text) ({ type: ADD_TODO, payload: { id: Date.now(), text, completed: false } }); export const toggleTodo (id) ({ type: TOGGLE_TODO, payload: id }); export const deleteTodo (id) ({ type: DELETE_TODO, payload: id }); // reducers.js const todoReducer (state [], action) { switch (action.type) { case ADD_TODO: return [...state, action.payload]; case TOGGLE_TODO: return state.map(todo todo.id action.payload ? { ...todo, completed: !todo.completed } : todo ); case DELETE_TODO: return state.filter(todo todo.id ! action.payload); default: return state; } }; // components/TodoApp.jsx import { useSelector, useDispatch } from react-redux; import { addTodo, toggleTodo, deleteTodo } from ../store/actions; function TodoApp() { const [text, setText] useState(); const todos useSelector(state state.todos); const dispatch useDispatch(); const handleSubmit (e) { e.preventDefault(); if (text.trim()) { dispatch(addTodo(text)); setText(); } }; return ( div form onSubmit{handleSubmit} input value{text} onChange{(e) setText(e.target.value)} / button typesubmit添加/button /form ul {todos.map(todo ( li key{todo.id} input typecheckbox checked{todo.completed} onChange{() dispatch(toggleTodo(todo.id))} / span{todo.text}/span button onClick{() dispatch(deleteTodo(todo.id))}删除/button /li ))} /ul /div ); }7.8 异步 Action使用 Redux Thunknpminstallredux-thunk// store/index.js import { createStore, applyMiddleware } from redux; import thunk from redux-thunk; import { rootReducer } from ./reducers; const store createStore(rootReducer, applyMiddleware(thunk)); // actions.js - 异步 Action Creator export const fetchUser (userId) { return async (dispatch) { dispatch({ type: FETCH_USER_START }); try { const response await fetch(/api/users/${userId}); const user await response.json(); dispatch({ type: FETCH_USER_SUCCESS, payload: user }); } catch (error) { dispatch({ type: FETCH_USER_ERROR, payload: error.message }); } }; }; // reducers.js const userReducer (state { data: null, loading: false, error: null }, action) { switch (action.type) { case FETCH_USER_START: return { ...state, loading: true, error: null }; case FETCH_USER_SUCCESS: return { ...state, loading: false, data: action.payload }; case FETCH_USER_ERROR: return { ...state, loading: false, error: action.payload }; default: return state; } };八、常见陷阱8.1 直接修改状态// ❌ 错误直接修改 const reducer (state [], action) { switch (action.type) { case ADD: state.push(action.payload); // 直接修改 return state; } }; // ✅ 正确返回新数组 const reducer (state [], action) { switch (action.type) { case ADD: return [...state, action.payload]; } };8.2 忘记返回默认状态// ❌ 错误忘记 default const reducer (state 0, action) { switch (action.type) { case INCREMENT: return state 1; // 缺少 default会返回 undefined } }; // ✅ 正确 const reducer (state 0, action) { switch (action.type) { case INCREMENT: return state 1; default: return state; } };九、练习题创建一个计数器 Redux 应用创建一个 Todo Redux 应用创建一个用户认证 Redux 应用十、小结概念说明Store存储状态的容器Action描述状态变化的对象Reducer纯函数执行状态变化Dispatch触发 Action 的方法Selector从 Store 读取状态