Day 8:状态管理原理
核心概念
状态管理 = React 的"大管家",帮你管好数据
| 不用状态管理 | 用状态管理 |
|---|
| 数据散得到处都是 | 集中在一个地方 |
| 传递 props 麻烦 | 随时随地都能用 |
| 很难追踪数据变化 | 一切都可追溯 |
常见状态管理方案
- useState - 组件内部状态,最简单
- Context - 跨组件共享,有性能问题
- Redux - 功能最全,代码多
- Zustand - 轻量简单,面试加分
useState
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
Context
const ThemeContext = React.createContext('light');
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
function Toolbar() {
const theme = useContext(ThemeContext);
return <div>{theme}</div>;
}
Redux
核心流程
Action → Dispatch → Reducer → State → View
代码示例
const counterReducer = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT': return state + 1;
case 'DECREMENT': return state - 1;
default: return state;
}
};
const store = createStore(counterReducer);
store.dispatch({ type: 'INCREMENT' });
store.getState();
createStore 简化实现
function createStore(reducer) {
let state;
let listeners = [];
const getState = () => state;
const dispatch = (action) => {
state = reducer(state, action);
listeners.forEach(listener => listener());
};
const subscribe = (listener) => {
listeners.push(listener);
return () => {
listeners = listeners.filter(l => l !== listener);
};
};
dispatch({ type: '@@INIT' });
return { getState, dispatch, subscribe };
}
Zustand
import { create } from 'zustand';
const useStore = create(set => ({
count: 0,
increase: () => set(state => ({ count: state.count + 1 })),
}));
function Counter() {
const { count, increase } = useStore();
return <button onClick={increase}>{count}</button>;
}
Zustand vs Redux:
| 特性 | Redux | Zustand |
|---|
| 代码量 | 多 | 极少 |
| 配置 | 需要创建 store、reducer、action | 一行代码 |
| Provider | 需要 | 不需要 |
面试高频问题
| 问题 | 答案要点 |
|---|
| React 状态管理有哪些方式? | useState, Context, Redux, Zustand |
| Redux 核心概念? | Store, Action, Reducer, Dispatch |
| Redux 为什么要用不可变数据? | 方便追踪变化、便于 time-travel |
| Context 的缺点? | 会导致所有消费者重渲染 |
| Redux vs Zustand? | Redux 完整但繁琐,Zustand 轻量 |
| 如何优化 Context 性能? | 拆分 Context,按需订阅 |
自测答案
1. Redux 的核心工作流程是什么?
Action → Dispatch → Reducer → New State → Subscribe → View
1. 组件派发 action(描述要做什么)
2. Redux 调用 reducer 计算新状态
3. 更新 store 中的 state
4. 通知所有订阅者
5. 组件重新渲染
2. 为什么 Redux 需要不可变数据?
- 变化追踪:用
=== 就能判断是否变化(O(1)),不用深比较
- 时间旅行:记录所有 state 历史,可回滚调试
- 性能优化:shouldComponentUpdate 更好用
3. Context 的性能问题及解决方案?
- 问题:Provider value 变化时,所有消费者都会重渲染
- 解决方案:
- 拆分成多个小 Context
- 用
memo 包裹消费组件
- 用
useMemo 保持 value 稳定
4. Zustand 相比 Redux 的优势?
- 代码量极少,一行代码创建 store
- 无需 Provider,直接用 hook
- 无需 action creator,函数直接更新
- 组件可以只订阅需要的字段