useContext结合useReducer管理状态
2024/8/26 | 字数检测:2452AI摘要
本文介绍了如何利用React的useReducer和useContext管理复杂状态,以替代useState。文章通过四个步骤详细阐述:首先创建两个Context(一个用于状态,一个用于dispatch函数);其次在顶层组件中将useReducer返回的状态和dispatch函数放入Context提供给子组件;然后子组件可直接使用useContext获取状态和修改函数,无需层层传递;最后推荐将reducer逻辑和Context提供者封装成独立的TasksProvider组件,实现状态逻辑的集中管理和模块化,从而提升代码可维护性。

本文参考 React 官方文档:使用 Reducer 和 Context 拓展你的应用,区别于 useState,更好的管理复杂的状态
主要就是利用useContext可以沿着组件向下传值,且无需考虑层级,和useReducer中 Reducer 用于管理状态
第一步:创建 Context
import { createContext } from "react";
export const TasksContext = createContext(null);
export const TasksDispatchContext = createContext(null);
第二步:将 state 和 dispatch 函数放入 context
import { TasksContext, TasksDispatchContext } from "./TasksContext.js";
export default function TaskApp() {
const [tasks, dispatch] = useReducer(tasksReducer, initialTasks);
// ...
return (
<TasksContext.Provider value={tasks}>
<TasksDispatchContext.Provider value={dispatch}>
...
</TasksDispatchContext.Provider>
</TasksContext.Provider>
);
}
第三步:在组件树中的任何地方使用 context
现在你不需要任何沿着组件树一层层传递状态和修改状态逻辑,只需要使用 state 和 dispatch,一切变得简单起来
export default function TaskList() {
const tasks = useContext(TasksContext);
// ...
export default function AddTask() {
const [text, setText] = useState('');
const dispatch = useContext(TasksDispatchContext);
// ...
return (
// ...
<button onClick={() => {
setText('');
dispatch({
type: 'added',
id: nextId++,
text: text,
});
}}>Add</button>
// ...
第四步:让我们把所有东西放到一个文件(非必须,但我推荐这样做)
此时,我们已经完成了随传随用随改变,不过我们的 state 仍然在最顶层组件TaskApp提供,我们试着将整个状态逻辑抽离出去,单独一个文件管理这些状态,显然这是我们想要的,代码模块更加独立
我们连接所有,让那个文件具有这些功能:
- 它将管理 reducer 的状态。
- 它将提供现有的 context 给组件树。
- 它将 把 children 作为 prop,所以你可以传递 JSX。
import { createContext } from "react";
//此处可以导入Reducer,初始状态值
export const TasksContext = createContext(null);
export const TasksDispatchContext = createContext(null);
//封装组件
export function TasksProvider({ children }) {
const [tasks, dispatch] = useReducer(tasksReducer, initialTasks);
return (
<TasksContext.Provider value={tasks}>
<TasksDispatchContext.Provider value={dispatch}>
{children}
</TasksDispatchContext.Provider>
</TasksContext.Provider>
);
}
现在我们一个文件来提供这所有关于状态的一切,使用时不用担心数据混乱,逻辑疯狂抽离让我们代码更好管理维护,让组件的作用更加明确单一,是一个好代码的标准之一,平时写代码要注意它们。
文档细节参考(useContext,useReducer):