教你如何理解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,可以构建一个简单而有效的状态管理模式,适用于中小规模的应用。这种方法不仅简化了状态管理,也减少了不必要的代码复杂度。

相关推荐
我命由我123451 分钟前
VSCode - VSCode 快速跳转标签页
开发语言·前端·ide·vscode·编辑器·html·js
爱学习的茄子28 分钟前
告别 useState 噩梦:useReducer 如何终结 React 状态管理混乱?
前端·深度学习·react.js
种子q_q38 分钟前
面试官:什么是Spring的三级缓存机制
后端·面试
油丶酸萝卜别吃42 分钟前
怎么判断一个对象是不是vue的实例
前端·javascript·vue.js
科技D人生1 小时前
Vue.js 学习总结(18)—— Vue 3.6.0-alpha1:性能“核弹“来袭,你的应用准备好“起飞“了吗?!
前端·vue.js·vue3·vue 3.6·vue3.6
鬼鬼_静若为竹1 小时前
我终于也是会写3d小游戏的人了,发个掘金显摆显摆
前端
weixin_470880261 小时前
行为型设计模式:解释器模式
设计模式·面试·解释器模式·代码规范·个人提升
Mintopia1 小时前
Three.js 滚动条 3D 视差动画原理解析
前端·javascript·three.js
啃火龙果的兔子2 小时前
在 React 中根据数值动态设置 SVG 线条粗细
前端·react.js·前端框架
蓝乐2 小时前
Angular项目IOS16.1.1设备页面空白问题
前端·javascript·angular.js