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

news2024/12/24 8:58:00

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 -> B

import { 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.coloradmin.cn/o/2230233.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java项目实战II基于Java+Spring Boot+MySQL的智能推荐的卫生健康系统(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 基于Java、…

《Linux系统编程篇》消息队列(Linux 进程间通信(IPC))——基础篇

文章目录 引言消息队列&#xff08;Message Queue&#xff09;消息队列的特点消息队列的特性消息队列的操作ipcs -q 拓展ipcrm 拓展注意事项 结论 “山重水复疑无路&#xff0c;柳暗花明又一村。” ——陆游 引言 《Linux系统编程篇》——基础篇首页传送门 想象一下&#xff0…

微服务设计模式 - 重试模式(Retry Pattern)

微服务设计模式 - 重试模式&#xff08;Retry Pattern&#xff09; 定义 重试模式&#xff08;Retry Pattern&#xff09;是一种微服务中的设计模式&#xff0c;用于在临时性失败&#xff08;如网络故障或暂时不可用的服务&#xff09;发生时&#xff0c;自动重新尝试请求&…

『 Linux 』网络传输层 - TCP(二)

文章目录 TCP六个标志位TCP的连接三次握手 四次挥手为什么是三次握手和四次挥手 重传机制 TCP六个标志位 在TCP协议报文的报头中存在一个用于标志TCP报文类型的标志位(不考虑保留标志位),这些标志位以比特位选项的方式存在,即对应标志位为0则表示为假,对应标志位为1则为真; SYN…

VLAN虚拟局域网,eNSP实验讲解

VLAN虚拟局域网&#xff0c;eNSP实验讲解 一、概念二、eNSP仿真实验1、实验一&#xff1a;vlan演示&#xff08;交换机端口access模式&#xff09;2、实验二&#xff1a;vlan演示&#xff08;交换机端口trunk模式&#xff09; 一、概念 VLAN&#xff08;Virtual Local Area Ne…

Ubuntu UFW防火墙规则与命令示例大全

在服务器安全领域&#xff0c;防火墙是守护网络安全的坚实盾牌。UFW&#xff08;Uncomplicated Firewall&#xff09;&#xff0c;即“不复杂的防火墙”&#xff0c;是一个运行在iptables之上的防火墙配置工具&#xff0c;它为Ubuntu系统默认提供了一个简洁的命令行界面&#x…

基于 Python 的 Django 框架开发的电影推荐系统

项目简介&#xff1a;本项目是基于 Python 的 Django 框架开发的电影推荐系统&#xff0c;主要功能包括&#xff1a; 电影信息爬取&#xff1a;获取并更新电影数据。数据展示&#xff1a;提供电影数据的列表展示。推荐系统&#xff1a;基于协同过滤算法实现个性化推荐。用户系…

ORB-SLAM2源码学习:ORBextractor.cc:IC_Angle 利用灰度质心法求解关键点方向角

ORB特征点&#xff1a; 特征点是由关键点和描述子两部分组成&#xff0c;关键点是指特征点在图像中的位置&#xff0c;描述子是用来描述关键点周围的像素信息。ORB关键点是在FAST关键点的基础上进行改进给像素增加了一个主方向&#xff0c;称为Oriented FAST。描述子在BRIEF的…

【设计模式】如何用C++实现依赖倒置

【设计模式】如何用C实现依赖倒置 一、什么是依赖倒置&#xff1f; 依赖倒置原则&#xff08;Dependency Inversion Principle&#xff0c;DIP&#xff09;是SOLID面向对象设计原则中的一项。它的核心思想是&#xff1a; 高层模块不应该依赖于低层模块&#xff0c;两者都应该…

‌植物神经紊乱患者,这些锻炼适合你!

植物神经紊乱是一种常见的心理疾病&#xff0c;其主要症状包括焦虑、抑郁、失眠等&#xff0c;严重时还可能出现心慌、气短、憋气、出汗异常等症状。然而&#xff0c;通过适量的锻炼&#xff0c;我们可以帮助调节自主神经系统&#xff0c;缓解这些症状。那么&#xff0c;植物神…

Golang | Leetcode Golang题解之第525题连续数组

题目&#xff1a; 题解&#xff1a; func findMaxLength(nums []int) (maxLength int) {mp : map[int]int{0: -1}counter : 0for i, num : range nums {if num 1 {counter} else {counter--}if prevIndex, has : mp[counter]; has {maxLength max(maxLength, i-prevIndex)} …

第十七届山东省职业院校技能大赛通知分享

近日&#xff0c;山东省教育厅联合相关部门发布了关于举办第十七届山东省职业院校技能大赛的通知&#xff0c;标志着这一旨在深化教育教学改革、推进产教融合与校企合作的重要赛事即将拉开帷幕。 据了解&#xff0c;本次大赛将设中等职业教育组和高等职业教育组&#xff0c;共包…

Angular实现gridview效果

说明&#xff1a;使用angular实现grid效果&#xff0c;支持文字图片多条数据展示 效果图: step1: <mat-grid-list cols"2" rowHeight"2:1"><mat-grid-tile *ngFor"let course of courses">{{ course }}</mat-grid-tile> &l…

web of sicence使用教程(研究生版)

学习视频链接 进入web of science 通过校园资料库进入进入&#xff0c;选择如下 核心检索规则 不区分字母大小写逻辑运算符 可以通过括号改变优先级 常用通配符 短语检索 检索界面 检索类型 选择数据库

2-8软件包管理

8.1 配置仓库 1.配置本地仓库 #进行代码安装前需要先进行仓库配置和挂载 [rootlocalhost ~]# cd /etc/yum.repos.d [rootlocalhost yum.repos.d]# vim base.repo [baseos] namebaseos baseurl/mnt/BaseOS gpgcheck0 [appstream] nameappstream baseurl/mnt/AppStream gp…

适配器模式:类适配器与对象适配器

适配器模式是一种结构性设计模式&#xff0c;旨在将一个接口转换成客户端所期望的另一种接口。它通常用于解决由于接口不兼容而导致的类之间的通信问题。适配器模式主要有两种实现方式&#xff1a;类适配器和对象适配器。下面&#xff0c;我们将详细探讨这两种方式的优缺点及适…

性能测试:性能测试流程与方法

性能测试流程是指在进行性能测试时所遵循的一系列步骤和阶段&#xff0c;以确保对系统的全面测试和评估。性能测试流程的具体步骤可能会因组织、项目和测试需求而有所不同。 性能测试流程 分析现状&#xff1a;首先需要对应用程序或系统进行详细的分析&#xff0c;了解其当前的…

使用WebStorm开发Vue3项目

记录一下使用WebStorm开发Vu3项目时的配置 现在WebStorm可以个人免费使用啦&#xff01;&#x1f929; 基本配置 打包工具&#xff1a;Vite 前端框架&#xff1a;ElementPlus 开发语言&#xff1a;Vue3、TypeScript、Sass 代码检查&#xff1a;ESLint、Prettier IDE&#xf…

Java已死,大模型才是未来?

作者&#xff1a;不惑_ 引言 在数字技术的浪潮中&#xff0c;编程语言始终扮演着至关重要的角色。Java&#xff0c;自1995年诞生以来&#xff0c;便以其跨平台的特性和丰富的生态系统&#xff0c;成为了全球范围内开发者们最为青睐的编程语言之一 然而&#xff0c;随着技术的…

Allegro: 开源的高级视频生成模型

我们很高兴地宣布 Allegro 的开源发布&#xff0c;这是 Rhymes AI 先进的文本到视频模型。Allegro 是一款功能强大的人工智能工具&#xff0c;能将简单的文字提示转化为高质量的视频短片&#xff0c;为人工智能生成视频领域的创作者、开发者和研究人员开辟了新的可能性。我们希…