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

相关推荐
J***Q2921 小时前
Vue数据可视化
前端·vue.js·信息可视化
ttod_qzstudio3 小时前
深入理解 Vue 3 的 h 函数:构建动态 UI 的利器
前端·vue.js
芳草萋萋鹦鹉洲哦3 小时前
【elemen/js】阻塞UI线程导致的开关卡顿如何优化
开发语言·javascript·ui
_大龄3 小时前
前端解析excel
前端·excel
1***s6323 小时前
Vue图像处理开发
javascript·vue.js·ecmascript
槁***耿4 小时前
JavaScript在Node.js中的事件发射器
开发语言·javascript·node.js
一叶茶4 小时前
移动端平板打开的三种模式。
前端·javascript
前端大卫4 小时前
一文搞懂 Webpack 分包:async、initial 与 all 的区别【附源码】
前端
U***49834 小时前
JavaScript在Node.js中的Strapi
开发语言·javascript·node.js
Want5954 小时前
HTML音乐圣诞树
前端·html