React轻量级状态管理方案(useReducer + Context API)
🤔 为什么需要轻量级状态管理?
在React应用开发中,随着组件层次的增加和状态复杂度的提升,传统的props传递方式会变得越来越繁琐:
- 多层级组件需要通过props逐层传递数据(props drilling)
- 多个组件共享同一份状态时,状态同步变得困难
- 组件间通信需要通过复杂的回调函数
- 大型状态管理库(如Redux)可能带来不必要的复杂性
对于中等规模的应用,我们可以使用React内置的useReducer和Context API组合,实现一个轻量级、高效的状态管理方案,既避免了props drilling,又不需要引入额外的依赖。
💡 基础概念
1. useReducer Hook
useReducer是React提供的一个Hook,用于管理复杂的状态逻辑。它类似于Redux的思想:
- 状态通过
reducer函数进行更新 - 状态更新需要派发(dispatch)一个动作(action)
reducer函数接收当前状态和动作,返回新的状态
语法:
const [state, dispatch] = useReducer(reducer, initialState);
2. Context API
Context API是React提供的一种在组件树中共享数据的方式,不需要通过props逐层传递:
- 使用
createContext创建一个Context对象 - 使用
Provider组件包裹需要共享数据的组件树 - 使用
useContext在子组件中获取共享数据
语法:
// 创建Context
const MyContext = createContext(defaultValue);
// 提供Context
<MyContext.Provider value={
value}>
{
/* 子组件 */}
</MyContext.Provider>
// 消费Context
const value = useContext(MyContext);
🚀 基础实现:计数器应用
让我们先通过一个简单的计数器应用,了解useReducer和Context API的基础用法。
1. 创建状态管理文件
// src/contexts/CounterContext.js
import React, {
createContext, useContext, useReducer } from 'react';
// 定义初始状态
const initialState = {
count: 0,
history: [0],
isUndoDisabled: true,
isRedoDisabled: true
};
// 定义action类型
const ActionTypes = {
INCREMENT: 'INCREMENT',
DECREMENT: 'DECREMENT',
RESET: 'RESET',
UNDO: 'UNDO',
REDO: 'REDO',
SET_COUNT: 'SET_COUNT'
};
// 创建reducer函数
const counterReducer = (state, action) => {
switch (action.type) {
case ActionTypes.INCREMENT:
return {
...state,
count: state.count + 1,
history: [...state.history, state.count + 1],
currentIndex: state.history.length,
isUndoDisabled: false,
isRedoDisabled: true
};
case ActionTypes.DECREMENT:
return {
...state,
count: state.count - 1,
history: [...state.history, state.count - 1],
currentIndex: state.history.length,
isUndoDisabled: false,
isRedoDisabled: true
};
case ActionTypes.RESET:
return {
...state,
count: 0,
history: [...state.history, 0],
currentIndex: state.history.length,
isUndoDisabled: false,
isRedoDisabled: true
};
case ActionTypes.UNDO:
if (state.currentIndex <= 0) return state;
const newIndex = state.currentIndex - 1;
return {
...state,
count: state.history[newIndex],
currentIndex: newIndex,
isUndoDisabled: newIndex === 0,
isRedoDisabled: false
};
case ActionTypes.REDO:
if (state.currentIndex >= state.history.length - 1) return state;
const nextIndex = state.currentIndex + 1;
return {
...state,
count: state.history[nextIndex],
currentIndex: nextIndex,
isUndoDisabled: false,
isRedoDisabled: nextIndex === state.history.length - 1
};
case ActionTypes.SET_COUNT:
return {
...state,
count: action.payload,
history: [...state.history.slice(0, state.currentIndex + 1), action.payload],
currentIndex: state.currentIndex + 1,
isUndoDisabled: false,
isRedoDisabled: true
};
default:
return state;
}
};
// 创建Context
const CounterContext = createContext(null);
// 创建Provider组件
export const CounterProvider = ({
children }) => {
const [state, dispatch] = useReducer(counterReducer, initialState);
// 定义操作函数
const actions = {
increment: () => dispatch({
type: ActionTypes.INCREMENT }),
decrement: () => dispatch({
type: ActionTypes.DECREMENT }),
reset

最低0.47元/天 解锁文章
1164

被折叠的 条评论
为什么被折叠?



