Context + useReducer
约 376 字大约 1 分钟
布欧-Lewyon
2026-05-15
组合使用
Context 传值 + useReducer 管理逻辑 = 轻量级全局状态管理。
// store.ts
interface Todo {
id: number
text: string
done: boolean
}
type TodoAction =
| { type: 'ADD'; payload: string }
| { type: 'TOGGLE'; payload: number }
| { type: 'DELETE'; payload: number }
function todoReducer(state: Todo[], action: TodoAction): Todo[] {
switch (action.type) {
case 'ADD':
return [...state, { id: Date.now(), text: action.payload, done: false }]
case 'TOGGLE':
return state.map(t => t.id === action.payload ? { ...t, done: !t.done } : t)
case 'DELETE':
return state.filter(t => t.id !== action.payload)
default:
return state
}
}// TodoContext.tsx
const TodoContext = createContext<Todo[]>([])
const TodoDispatchContext = createContext<React.Dispatch<TodoAction>>(() => {})
function TodoProvider({ children }: { children: React.ReactNode }) {
const [todos, dispatch] = useReducer(todoReducer, [])
return (
<TodoDispatchContext.Provider value={dispatch}>
<TodoContext.Provider value={todos}>
{children}
</TodoContext.Provider>
</TodoDispatchContext.Provider>
)
}// 使用
function TodoApp() {
const [text, setText] = useState('')
const todos = useContext(TodoContext)
const dispatch = useContext(TodoDispatchContext)
return (
<div>
<input value={text} onChange={e => setText(e.target.value)} />
<button onClick={() => { dispatch({ type: 'ADD', payload: text }); setText('') }}>
Add
</button>
<ul>
{todos.map(t => (
<li key={t.id}>
<span onClick={() => dispatch({ type: 'TOGGLE', payload: t.id })}>
{t.done ? '✅' : '⬜'} {t.text}
</span>
<button onClick={() => dispatch({ type: 'DELETE', payload: t.id })}>×</button>
</li>
))}
</ul>
</div>
)
}
// App
function App() {
return (
<TodoProvider>
<TodoApp />
</TodoProvider>
)
}Context 性能问题
Context 值变化时,所有 Consumer 都会重渲染。
// ❌ 价值变化导致所有 Consumer 重渲染
function UserProvider({ children }) {
const [user, setUser] = useState(null)
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
)
}
// ✅ 拆分 Context,减少重渲染范围
function UserSplitProvider({ children }) {
const [user, setUser] = useState(null)
return (
<UserValueContext.Provider value={user}>
<UserSetterContext.Provider value={setUser}>
{children}
</UserSetterContext.Provider>
</UserValueContext.Provider>
)
}小结
- Context + useReducer = 轻量 Redux(状态 + 派发分离)。
- Context 传 dispatch,任意子组件可触发状态更新。
- 拆分 Context(值 / 设置函数)减少不必要重渲染。
- 适合中小型应用,大型应用推荐 Zustand / Redux Toolkit。
上一节:闭包陷阱 下一节:Zustand 轻量状态库
