Redux 多组件状态管理
Redux 是一个 JavaScript 状态容器,通过集中式存储和单向数据流实现多个组件间的状态共享与通信。它是处理跨组件复杂状态的行业标准方案。
一、核心概念
Redux 的状态管理围绕三个核心概念展开:
Store:唯一的、全局的状态树。所有共享状态都存储在一个 store 对象中。
Action:描述发生了什么的普通对象,包含 type 字段表示操作类型,可选的 payload 携带数据。
Reducer:纯函数,接收当前状态和 action,返回新的状态。它决定了状态如何响应各种操作。
数据流是单向的:组件 dispatch 一个 action → reducer 处理 → store 更新 → 所有订阅的组件收到通知。
二、基本实现
创建 store
import { createStore } from 'redux'
const initialState = {
count: 0,
todos: [],
}
function reducer(state = initialState, action: any) {
switch (action.type) {
case 'INCREMENT':
return { ...state, count: state.count + 1 }
case 'ADD_TODO':
return { ...state, todos: [...state.todos, action.payload] }
default:
return state
}
}
export const store = createStore(reducer)在函数组件中使用(推荐方式)
使用 useSelector 获取状态,使用 useDispatch 发送 action:
import { useSelector, useDispatch } from 'react-redux'
function Counter() {
const count = useSelector((state: any) => state.count)
const dispatch = useDispatch()
return (
<div>
<p>计数:{count}</p>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>增加</button>
</div>
)
}
function TodoList() {
const todos = useSelector((state: any) => state.todos)
const dispatch = useDispatch()
const handleAddTodo = (text: string) => {
dispatch({ type: 'ADD_TODO', payload: text })
}
return (
<div>
{todos.map((todo, i) => (
<li key={i}>{todo}</li>
))}
</div>
)
}在类组件中使用(旧方式)
使用 connect 高阶组件将状态和 dispatch 方法映射到 props:
import { connect } from 'react-redux'
class Counter extends React.Component<any> {
render() {
const { count, increment } = this.props
return (
<div>
<p>计数:{count}</p>
<button onClick={increment}>增加</button>
</div>
)
}
}
const mapStateToProps = (state: any) => ({
count: state.count,
})
const mapDispatchToProps = (dispatch: any) => ({
increment: () => dispatch({ type: 'INCREMENT' }),
})
export default connect(mapStateToProps, mapDispatchToProps)(Counter)三、最佳实践
状态划分:只把跨组件共享的全局状态放在 Redux 中。组件的局部状态(如表单输入框的值)继续用 useState 管理。
状态扁平化:避免深层嵌套的状态结构。扁平的状态更易于更新和维护。
// ✗ 避免深层嵌套
const state = {
user: {
profile: {
personal: {
name: 'John',
},
},
},
}
// ✓ 优先扁平结构
const state = {
userName: 'John',
userEmail: 'john@example.com',
}Action 常量化:定义常量避免 action type 的拼写错误。
const INCREMENT = 'INCREMENT'
const ADD_TODO = 'ADD_TODO'
dispatch({ type: INCREMENT })精确订阅:只订阅组件真正需要的状态片段,避免不必要的重新渲染。
// ✗ 订阅整个状态
const state = useSelector((s) => s)
// ✓ 只订阅需要的部分
const count = useSelector((s) => s.count)
const todos = useSelector((s) => s.todos)Reducer 职责单一:为不同的状态片段创建不同的 reducer,然后用 combineReducers 组合。
import { createStore, combineReducers } from 'redux'
const countReducer = (state = 0, action: any) => {
return action.type === 'INCREMENT' ? state + 1 : state
}
const todoReducer = (state: any[] = [], action: any) => {
return action.type === 'ADD_TODO' ? [...state, action.payload] : state
}
const rootReducer = combineReducers({
count: countReducer,
todos: todoReducer,
})
const store = createStore(rootReducer)四、性能优化
使用 React.memo 避免不必要的渲染
const TodoItem = React.memo(({ todo, onDelete }: any) => {
return (
<div>
<span>{todo}</span>
<button onClick={onDelete}>删除</button>
</div>
)
})批量更新:避免在短时间内多次 dispatch,可以合并成一个 action。
// ✗ 多次 dispatch,触发多次重新渲染
dispatch({ type: 'SET_NAME', payload: 'John' })
dispatch({ type: 'SET_EMAIL', payload: 'john@example.com' })
// ✓ 一次 dispatch,一次重新渲染
dispatch({
type: 'UPDATE_USER',
payload: { name: 'John', email: 'john@example.com' },
})一句话记住:Redux 通过一个全局 store 存储所有共享状态,组件通过 dispatch action 触发状态更新,reducer 定义状态如何变化,store 的订阅机制自动通知相关组件。合理划分状态、精确订阅、扁平化结构是维持性能的关键。