教你如何理解useContext加上useReducer

一.首先我们要知道useContext和useReducer是什么?

useContext和useReducer都是react中的hook

useContext

1.useContext的定义和作用

它是用于函数组件消费它是一个全局上下文,用于处理跨层级组件通信问题,它避免了组件之间props层层传递的复杂性,它可以直接获取到context中的某个值而不用通过props传递。

2.useContext的使用

创建useContext

js 复制代码
const ThemeContext = creatContext('light');

使用Provider提供值

jsx 复制代码
<ThemeContext.Provider value={theme}>
    // 这里的Theme为自定义的value值
....// 中间为组件
<ThemeContext.Provider/>

在子组件使用useContext获取值

js 复制代码
const theme = useContext(ThemeContext)

以下为完整示例代码

jsx 复制代码
import React, { useContext, useReducer } from 'react';
// 1. 创建 Context
const ThemeContext = React.createContext();
// 2. 创建组件
function App() {
  const [theme, toggleTheme] = useReducer(
    (state) => (state === 'light' ? 'dark' : 'light'),
    'light'
  );
  return (
    // 3. 提供 Context 值
    <ThemeContext.Provider value={theme}>
      <button onClick={toggleTheme}>切换主题</button>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

// 中间组件(不需要传递 props)
function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

// 4. 使用 useContext 获取 Context 值
function ThemedButton() {
  const theme = useContext(ThemeContext);

  return (
    <button style={{ background: theme === 'dark' ? '#333' : '#eee', color: theme === 'dark' ? '#fff' : '#000' }}>
      当前主题:{theme}
    </button>
  );
}

export default App;

useReducer

1.useReducer的定义和作用

它为管理复杂的状态逻辑提供了一种替代useState的方法,它是一种响应式状态管理。

Reducer是一个纯函数纯函数既是1.相同的输入值会得到相同的输出值2.无副作用不会对外部产生影响如:不改变全局变量,不发送网络请求,不操作DOM等。Reducer它接受两个参数state(当前状态) 和 action(动作)并且返回一个新的状态
dispatch用于发送动作到Reducer中,你调用一个dispatch并传入一个动作对象,reducer会根据整个动作来更新状态

2.useReducer的用法

  1. 定义 Reducer 函数:根据应用的业务逻辑定义 reducer 函数。该函数接收当前状态和动作作为参数,并返回新的状态。
  2. 使用 useReducer Hook :在组件中使用 useReducer 来初始化状态和 reducer 函数。useReducer 返回当前状态和 dispatch 方法。
  3. 分发动作:通过调用 dispatch 方法并传入动作对象来触发状态更新。
jsx 复制代码
import React, { useReducer } from 'react';

// 定义 Reducer 函数
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function Counter() {
  // 初始化状态为 { count: 0 },并指定 reducer 函数
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </>
  );
}

useContext和useReducer配合使用

什么时候使用useContext 1.当我们想多个层级组件共享状态或配置时 2.避免props一层层传递

什么时候使用useReducer 1.当组件的状态逻辑复杂时,例如涉及多个子值的状态,或者下一个状态依赖于前一个状态。 2.当下一个状态依赖于前一个状态时,使用 useReducer 可以避免一些潜在的副作用问题。

所以我们常常将useContext和useReducer一起使用

1. 创建 Context

首先,创建一个 React Context 来包裹你的应用状态和 dispatch 函数。

jsx 复制代码
import React, { createContext, useReducer } from 'react';

const AppContext = createContext();

const initialState = {
  count: 0,
};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}
2. 创建 Provider 组件

接下来,创建一个 Context Provider 组件,该组件内部使用 useReducer 来管理状态,并通过 value 属性向子组件暴露状态和 dispatch 方法。

jsx 复制代码
export const AppProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <AppContext.Provider value={{ state, dispatch }}>
      {children}
    </AppContext.Provider>
  );
};
3. 在顶层组件中使用 Provider

确保在你的应用顶层组件中使用这个 Provider,以便所有子组件都可以访问到状态和 dispatch 方法。

jsx 复制代码
import React from 'react';
import ReactDOM from 'react-dom';
import { AppProvider } from './AppProvider'; // 假设文件名为 AppProvider.js
import App from './App'; // 你的主应用组件

ReactDOM.render(
  <AppProvider>
    <App />
  </AppProvider>,
  document.getElementById('root')
);
4. 使用 useContext 钩子在组件中消费状态

最后,在需要访问状态或触发状态更新的组件中,使用 useContext 钩子来获取当前状态和 dispatch 方法。

javascript 复制代码
javascript
深色版本
import React, { useContext } from 'react';
import { AppContext } from './AppProvider';

function Counter() {
  const { state, dispatch } = useContext(AppContext);

  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </>
  );
}

export default Counter;

总结

我们通过结合使用 useReduceruseContext,可以构建一个简单而有效的状态管理模式,适用于中小规模的应用。这种方法不仅简化了状态管理,也减少了不必要的代码复杂度。

相关推荐
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅7 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅7 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊7 小时前
jwt介绍
前端