当前位置: 首页 > news >正文

React中常用的hook函数(二)——useReducer和useContext

React中常用的hook函数(一)——useState和useEffect_usestate useeffect-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/Mrs_Lupin/article/details/142905749?sharetype=blogdetail&sharerId=142905749&sharerefer=PC&sharesource=Mrs_Lupin&spm=1011.2480.3001.8118React中常用的hook函数(二)——useMemo和useCallback-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/Mrs_Lupin/article/details/143424548?sharetype=blogdetail&sharerId=143424548&sharerefer=PC&sharesource=Mrs_Lupin&spm=1011.2480.3001.8118

一、useReducer

1.作用:

用于管理组件状态,尤其在状态逻辑较复杂或者状态依赖于之前状态时特别有用。它通常用于代替 useState

2.语法:

useReducer函数

useReducer 接受三个参数:

  1. reducer 函数:用于定义状态如何随着动作(action)变化的纯函数。
  2. 初始状态:用于设置状态的初始值。
  3. 可选的初始化函数:如果你的初始状态需要计算,可以传入这个函数。

返回值是一个数组,包含当前状态和一个 dispatch 函数,用于发送动作以更新状态。

reducer 函数

reducer 函数接受两个参数:

  1. 当前状态(state)
  2. 动作(action)

它必须返回一个新的状态对象。

3.基础用法:

(1)定义一个reducer函数(根据不同的action返回不同的新状态)

function reducer(state, action) {switch (action.type) {case 'increment':return { count: state.count + 1 };case 'decrement':return { count: state.count - 1 };default:return { count: state.count };}
}

(2)在组件中调用useReducer,并传入reducer函数和状态的初始值

const initialState = { count: 0 };
function Counter() {const [state, dispatch] = useReducer(reducer, initialState);...
}

(3)事件发生时,通过dispatch函数分派一个action对象(通知reducer要返回哪个新状态并渲染UI)

function Counter() {...dispatch({ type: 'increment' })
}

 (4)分派action时传参

使用示例

下面是一个使用 useReducer 的简单计数器示例:

import React, { useReducer } from 'react';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 };case 'update':return { count: action.payload };default:return { count: state.count };}
}function Counter() {const [state, dispatch] = useReducer(reducer, initialState);return (<>Count: {state.count}<button onClick={() => dispatch({ type: 'increment' })}>+</button><button onClick={() => dispatch({ type: 'decrement' })}>-</button><button onClick={() => dispatch({ type: 'update', payload: 100 })}>to 100</button></>);
}export default Counter;

4.为什么要使用useReducer

  • 状态逻辑复杂:当状态逻辑涉及多个子值或者状态依赖于之前的状态时,使用useReducer可以更好地组织代码。useState适用于管理简单状态,如布尔值、数字、字符串等,或者只有几个状态值需要管理。
  • 可读性:使用 reducer 函数可以使状态更新的逻辑更加集中,便于理解和维护。
  • 调试:可以更容易地跟踪状态变化,特别是在大型应用中。

二、useContext

1.作用

在函数组件中访问 React 上下文(Context),可以在组件树中跨层级传递数据(通信)

2.实现步骤

(1)使用 createContext方法创建一个上下文对象Ctx

import { createContext, useContext } from "react"// 1. createContext方法创建一个上下文对象const MsgContext = createContext()

(2)在顶层组件(App)中通过 Ctx.Provider 组件提供数据

function App () {const msg = 'this is app msg'return (<div>{/* 2. 在顶层组件 通过Provider组件提供数据 */}<MsgContext.Provider value={msg}>this is App<A /></MsgContext.Provider></div>)
}

(3)在底层组件(B)中通过 useContext 钩子函数获取消费数据

function B () {// 3. 在底层组件 通过useContext钩子函数使用数据const msg = useContext(MsgContext)return (<div>this is B compnent,{msg}</div>)
}

示例代码

// App -> A -> Bimport { createContext, useContext } from "react"// 1. createContext方法创建一个上下文对象const MsgContext = createContext()function A () {return (<div>this is A component<B /></div>)
}function B () {// 3. 在底层组件 通过useContext钩子函数使用数据const msg = useContext(MsgContext)return (<div>this is B compnent,{msg}</div>)
}function App () {const msg = 'this is app msg'return (<div>{/* 2. 在顶层组件 通过Provider组件提供数据 */}<MsgContext.Provider value={msg}>this is App<A /></MsgContext.Provider></div>)
}export default App

3. 多重上下文

如果需要使用多个上下文,可以多次调用 useContext

import React, { createContext, useContext, useState } from 'react';// 创建主题上下文
const ThemeContext = createContext();
// 创建用户上下文
const UserContext = createContext();const App = () => {const [theme, setTheme] = useState('light');const [user, setUser] = useState({ name: 'John Doe' });return (<ThemeContext.Provider value={{ theme, setTheme }}><UserContext.Provider value={{ user, setUser }}><UserProfile /></UserContext.Provider></ThemeContext.Provider>);
};const UserProfile = () => {//在底层组件中获取数据const { theme, setTheme } = useContext(ThemeContext);const { user } = useContext(UserContext);return (<div style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff' }}><h1>{user.name}</h1><button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>Toggle Theme</button></div>);
};

4. 注意事项

  • 性能考虑:当 Provider 的 value 改变时,所有使用该上下文的组件会重新渲染,因此可以通过缓存(如 useMemo)来优化性能。
  • 作用域:上下文的值是从最近的 Provider 组件中获取的,所以要确保 Provider 包裹住需要使用该上下文的组件。

5.结合useReducer

useReducer 也常与 useContext 结合使用,以便在组件树中共享状态:

使用步骤

(1)使用 useReducer 管理状态

useReducer 是一个 React Hook,适用于管理复杂的状态逻辑。它接收一个 reducer 函数和初始状态,并返回当前状态和一个 dispatch 函数。

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)创建上下文

通过 createContext 创建一个上下文,来共享状态和 dispatch 函数。

const StateContext = React.createContext();
(3)创建提供者组件

定义一个提供者组件,将状态和 dispatch 通过上下文传递给子组件。

function StateProvider({ children }) {const [state, dispatch] = useReducer(reducer, initialState);return (<StateContext.Provider value={{ state, dispatch }}>{children}</StateContext.Provider>);
}
(4)在子组件中使用上下文

在需要访问状态和 dispatch 的子组件中,使用 useContext 来获取这些值。

const ChildComponent = () => {const { state, dispatch } = useContext(StateContext);return (<div><p>Count: {state.count}</p><button onClick={() => dispatch({ type: 'increment' })}>Increment</button><button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button></div>);
};
(5)组合使用

在应用的根组件中,将 StateProvider 包裹在需要访问状态的组件树上。

const App = () => (<StateProvider><ChildComponent /></StateProvider>
);

通过这种方式,任何嵌套在 StateProvider 内的组件都可以访问和更新共享状态,使状态管理更加集中和高效。


http://www.mrgr.cn/news/63455.html

相关文章:

  • 哪个牌子的宠物空气净化器好?口碑好的宠物空气净化器推荐!
  • angular实现dialog弹窗
  • 计算机网络(Ⅵ)应用层原理
  • vulhub之Spring篇
  • Mysql数据库 | 第六章 | 表复制和去重 | 合并查询 | 外连接 | 主键 | 外键 | check约束
  • Rust:Vec<u8> 与 [u8] 之间的转换
  • C++11之新特性 --- function包装器与lambda表达式
  • AI直播带货场景切换模块的搭建!
  • 第14课 异常处理
  • 沙盒正在源代码防泄漏行业盛行
  • 【MySQL系列】理解 `utf8mb4` 和 `utf8mb4_unicode_ci`
  • ABAP OOALV
  • 如何打造美颜功能的视频平台?美颜SDK的开发与应用详解
  • 软件测试·用例设计都有哪些设计方法?这些设计方法适用于什么场景?
  • openGauss在银河麒麟V10 ARM平台编译安装(一)
  • 关于三色标记算法的理解
  • Git 子模块初始化和管理
  • 【Python游戏开发】猜数字游戏
  • Anolis(龙蜥)系统介绍
  • Linux中部署PostgreSQL保姆级教程
  • 二叉树算法题
  • 数据泄露后的安全重构:文件安全再思考
  • Java-实现重试机制并防止短时间内多次尝试
  • 2024网盘市场扫描 细则功能逐一较量
  • 使用 fzf 实现文件快速查找、打开及执行
  • Windows SEH异常处理讨论