一、Context API 深度应用
1. 核心实现原理
通过createContext
创建上下文对象,使用Provider组件包裹需要共享状态的组件树,子组件通过useContext
Hook或Consumer组件消费数据。
代码示例(主题切换场景):
// 创建上下文(带类型定义)
type ThemeContextType = {theme: 'light' | 'dark';toggleTheme: () => void;
};const ThemeContext = createContext<ThemeContextType | null>(null);// Provider组件封装
export const ThemeProvider = ({ children }) => {const [theme, setTheme] = useState<'light' | 'dark'>('light');// 使用useCallback避免重复渲染const toggleTheme = useCallback(() => {setTheme(prev => prev === 'light' ? 'dark' : 'light');}, []);// 使用useMemo优化对象引用const value = useMemo(() => ({ theme, toggleTheme }), [theme]);return (<ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>);
};// 消费组件
const ThemeButton = () => {const context = useContext(ThemeContext);if (!context) throw new Error("Missing ThemeProvider");return (<button style={{ background: context.theme === 'dark' ? '#333' : '#fff',color: context.theme === 'dark' ? '#fff' : '#333'}}onClick={context.toggleTheme}>Toggle Theme</button>);
};
最佳实践:
- 类型安全:结合TypeScript定义上下文类型
- 性能优化:使用
useMemo
/useCallback
避免无效渲染 - 错误边界:强制Provider包裹检查
- 模块化:按业务域拆分多个Context
二、Redux 现代工程实践
1. 架构演进
推荐使用Redux Toolkit(RTK)简化传统Redux的模板代码,结合React-Redux实现高效状态管理。
代码示例(计数器场景):
// store.ts
import { configureStore, createSlice } from '@reduxjs/toolkit';const counterSlice = createSlice({name: 'counter',initialState: { value: 0 },reducers: {increment: state => { state.value += 1 },decrement: state => { state.value -= 1 },incrementBy: (state, action: PayloadAction<number>) => {state.value += action.payload}}
});export const store = configureStore({reducer: {counter: counterSlice.reducer}
});// App.tsx
import { Provider } from 'react-redux';
import { useAppSelector, useAppDispatch } from './hooks';const CounterDisplay = () => {const count = useAppSelector(state => state.counter.value);return <div>{count}</div>;
};const CounterControls = () => {const dispatch = useAppDispatch();return (<><button onClick={() => dispatch(counterSlice.actions.increment())}>+</button><button onClick={() => dispatch(counterSlice.actions.decrement())}>-</button></>);
};
核心优势:
- 不可变数据管理(通过Immer实现)
- 中间件支持(Redux-Thunk/Saga)
- 时间旅行调试(Redux DevTools)
- 类型安全(TypeScript深度集成)
三、选型决策树
维度 | Context API | Redux |
---|---|---|
适用场景 | 中小型应用/局部状态共享 | 大型复杂应用/全局状态管理 |
学习曲线 | 低(React内置) | 中高(需掌握中间件等概念) |
性能优化 | 需手动优化 | 内置性能优化 |
调试能力 | 基础React DevTools | 时间旅行调试 11 |
异步处理 | 需结合useEffect/自定义Hook | 内置中间件支持 |
四、工程化建议
-
状态分层策略
- 组件级:
useState
/useReducer
- 模块级:Context API
- 应用级:Redux
- 服务级:React Query/SWR
- 组件级:
-
性能优化要点
- Context:拆分高频/低频更新Context
- Redux:使用
reselect
创建记忆化selector - 通用:避免在渲染函数中创建新对象
-
代码规范
// Bad: 直接传递新对象导致无效渲染 <MyContext.Provider value={{ theme, toggleTheme }}>// Good: 使用useMemo优化 const value = useMemo(() => ({ theme, toggleTheme }), [theme])
-
错误处理
- 添加状态变更日志
- 使用Redux中间件统一错误处理
- 实现Context兜底默认值
五、常见陷阱及解决方案
-
Context渲染风暴
- 现象:Provider值变化导致所有消费者重新渲染
- 方案:拆分Context / 使用
memo
-
Redux状态冗余
- 现象:store中存储非全局状态
- 方案:遵循最小状态原则
-
异步状态竞争
// 使用AbortController取消过期请求 const fetchUser = createAsyncThunk('user/fetch',async (userId, { signal }) => {const response = await fetch(`/users/${userId}`, { signal });return response.json();} );
在工程实践中,建议:
- 中小型项目优先使用Context API + TypeScript
- 复杂应用采用Redux Toolkit + RTK Query
- 混合方案:Redux管理核心业务流,Context处理UI状态
最终选型需综合考虑项目规模、团队经验和长期维护成本。对于新项目,可以从Context API起步,随着复杂度增长逐步引入Redux。