React 高级教程

news2024/7/4 5:59:54

在这里插入图片描述


目录

  • 前言
  • setState
  • 函数式编程
  • Hooks
  • My Hooks
  • useState
    • 定义
    • 原理
    • 函数式更新
      • reduce 方法
      • react 源码
  • useEffect
    • 定义
    • 原理
    • 无限循环
  • useCallback
    • 定义
    • 原理
  • useMemo
    • 定义
    • 比较
  • Redux
  • useReducer
    • 定义
    • 使用
    • 应用
  • useContext


前言

在现代前端开发中,React已经成为了一种无法忽视的技术。它的函数式编程模式,以及强大的Hooks API,为我们提供了一种全新的编程范式,使得我们可以更加灵活、高效地构建用户界面。

在这篇文章中,我们将深入探讨React的函数式编程,以及Hooks的定义和原理。我们将详细介绍一些常见的Hooks,如useState、useEffect、useCallback、useMemo、useContext和useReducer等,帮助你更好地理解和使用这些强大的工具。无论你是React的新手,还是有一定经验的开发者,我相信你都能在这篇文章中找到有价值的内容。让我们一起,深入探索React的世界。

setState

setState 本身代码的执行肯定是同步的,这里的异步是指是多个 state 会合成到一起进行批量更新。

函数式编程

这篇文章写的真的太好了,一定要读:简明 JavaScript 函数式编程——入门篇。
总结一下: 函数式编程有两个核心概念。

  • 数据不可变(无副作用): 它要求你所有的数据都是不可变的,这意味着如果你想修改一个对象,那你应该创建一个新的对象用来修改,而不是修改已有的对象。
  • 无状态: 主要是强调对于一个函数,不管你何时运行,它都应该像第一次运行一样,给定相同的输入,给出相同的输出,完全不依赖外部状态的变化。

纯函数带来的意义。

  • 便于测试和优化:这个意义在实际项目开发中意义非常大,由于纯函数对于相同的输入永远会返回相同的结果,因此我们可以轻松断言函数的执行结果,同时也可以保证函数的优化不会影响其他代码的执行。
  • 可缓存性:因为相同的输入总是可以返回相同的输出,因此,我们可以提前缓存函数的执行结果。
  • 更少的 Bug:使用纯函数意味着你的函数中不存在指向不明的 this,不存在对全局变量的引用,不存在对参数的修改,这些共享状态往往是绝大多数 bug 的源头。

Hooks

用动画和实战打开 React Hooks(一):useState 和 useEffect - 掘金
用动画和实战打开 React Hooks(二):自定义 Hook 和 useCallback - 掘金
用动画和实战打开 React Hooks(三):useReducer 和 useContext - 掘金

1.png

2.png

  • Hooks **只能用于 React 函数式组件,**组件的渲染的状态、事件处理函数每一次都是独立的。

My Hooks

function useBodyScrollPosition() {
  const [scrollPosition, setScrollPosition] = useState(null);

  useEffect(() => {
    const handleScroll = () => setScrollPosition(window.scrollY);
    document.addEventListener('scroll', handleScroll);
    return () =>
      document.removeEventListener('scroll', handleScroll);
  }, []);

  return scrollPosition;
}
  • 表面上:一个命名格式为 useXXX 的函数,但不是 React 函数式组件
  • 本质上:内部通过使用 React 自带的一些 Hook (例如 useState 和 useEffect )来实现某些通用的逻辑
  • 推荐的库:React Use 、aHooks、Umi Hooks

useState

定义

const [state, setState] = useState(initialValue);

其中 state 就是一个状态变量,setState 是一个用于修改状态的 Setter 函数,而 initialValue 则是状态的初始值

原理

1.png

  1. 在初次渲染时,我们通过 useState 定义了多个状态;
  2. 每调用一次 useState ,都会在组件之外生成一条 Hook 记录,同时包括状态值(用 useState 给定的初始值初始化)和修改状态的 Setter 函数;
  3. 多次调用 useState 生成的 Hook 记录形成了一条链表
  4. 触发 onClick 回调函数,调用 setS2 函数修改 s2 的状态,不仅修改了 Hook 记录中的状态值,还即将触发重渲染

函数式更新

reduce 方法

const nums = [1, 2, 3]
const value = nums.reduce((acc, next) => acc + next, 0)
  • next 是遍历数组nums的值,acc默认值自定义,新的值是函数的返回值
  • 特点是只返回一个值,不修改输入值

react 源码

function basicStateReducer(state, action) {
  return typeof action === 'function' ? action(state) : action;
}

1.png

2.png

  • 详细实现可以看链接文章的动态图
  • 静态更新值直接返回结果
  • 函数更新值会先把当前数据状态传入函数并计算结果返回

useEffect

定义

useEffect(() => {
  const intervalId = setInterval(doSomething(), 1000);
  return () => clearInterval(intervalId);
});
  • effectFn 是一个执行某些可能具有副作用的 Effect 函数(例如数据获取、设置/销毁定时器等),它可以返回一个清理函数(Cleanup),例如大家所熟悉的 setInterval 和 clearInterval
    • 每个 Effect 必然在渲染之后执行,因此不会阻塞渲染,提高了性能
    • 在运行每个 Effect 之前,运行前一次渲染的 Effect Cleanup 函数(如果有的话)
    • 当组件销毁时,运行最后一次 Effect 的 Cleanup 函数
  • 依赖数组选项:
    • 不写,每一次渲染后执行
    • [],只会在组件初次渲染执行
    • [a,b]会在依赖项发生变化执行
    • 判断数据是否发生改变使用 Object.is,对于基本数据类型可以直接判断(和===相似,不同点在于NAN为true,0和-0为false),但对于对象类型就判断在堆内存的引用地址是否发生改变

原理

1.png

  1. useState 和 useEffect 在每次调用时都被添加到 Hook 链表中;
  2. useEffect 还会额外地在一个队列中添加一个等待执行的 Effect 函数;
  3. 在渲染完成后,依次调用 Effect 队列中的每一个 Effect 函数。

无限循环

  • 依赖项在事件的内部更新,导致触发渲染 => 触发 Effect => 修改状态 => 触发重渲染的无限循环
  • 要正确传递依赖项,特别是被useState 定义和引用的数据类型

useCallback

定义

const memoizedCallback = useCallback(callback, deps);
  • useCallback 是一个允许你在多次渲染中缓存函数的 React Hook。
  • 第一个参数 callback 就是需要记忆的函数,第二个参数就是大家熟悉的 deps 参数
  • 在 Memoization 的上下文中,这个 deps 的作用相当于缓存中的键(Key),如果键没有改变,那么就直接返回缓存中的函数,如果有改变,就生成新的函数并缓存
  • 在大多数情况下,我们都是传入空数组 [] 作为 deps 参数,这样 useCallback 返回的就始终是同一个函数,永远不会更新

原理

1.png

2.png

  • 组件状态更新或者props改变会导致组件重新渲染,如果需要传递函数给子组件,那么一般的函数每次就会定义新的函数,导致子组件渲染(无法使用 memo 跳过)
  • 引用数据类型函数永远指向相同的堆内存地址,可以保证函数在初始化定义之后就不改变

useMemo

定义

const cachedValue = useMemo(calculateValue, dependencies)
  • useMemo 是一个 React Hook,它在每次重新渲染的时候能够缓存计算的结果

比较

  • useMemo 用于缓存结果,useCallback用于缓存值
function useCallback(fn, dependencies) {
  return useMemo(() => fn, dependencies);
}

Redux

1.png
堪称 React 版本的 Pinia,这才是你该选的 React 状态管理库! - 掘金

  • redux 是通过全局的状态管理来实现数据的通信
  • 和之前使用的 vuex 差不多,但现在有更好的状态管理库可以使用

useReducer

定义

const [state, dispatch] = useReducer(reducer, initialArg, init);
  1. 第一个参数 reducer 显然是必须的,它的形式跟 Redux 中的 Reducer 函数完全一致,即 (state, action) => newState。
  2. 第二个参数 initialArg 就是状态的初始值。
  3. 第三个参数 init 是一个可选的用于懒初始化(Lazy Initialization)的函数,这个函数返回初始化后的状态。

使用

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

function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
    </>
  );
}
  • 定义函数和初始状态,获取 state 和 dispatch 函数
  • 通过传入参数(带上类型),在reducer函数中修改并返回新的值

应用

  • 简单的状态修改更新 useState 够用
  • 对于需要维护的状态本身比较复杂,多个状态之间相互依赖、修改状态的过程比较复杂可以使用
  • 例子如下:
// 用于懒初始化的函数
function init(initialState) {
  return {
    past: [],
    present: initialState,
    future: [],
  };
}

// Reducer 函数
function reducer(state, action) {
  const { past, future, present } = state;
  switch (action.type) {
    case 'UNDO':
      return {
        past: past.slice(0, past.length - 1),
        present: past[past.length - 1],
        future: [present, ...future],
      };
    case 'REDO':
      return {
        past: [...past, present],
        present: future[0],
        future: future.slice(1),
      };
    default:
      return state;
  }
}

useContext

使用 Context 深层传递参数 – React 中文文档

1.png

  • Context 使组件向其下方的整个树提供信息,会穿过中间的任何组件
  • 通过 useContext ,我们就可以轻松地让所有组件都能获取到 dispatch 函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1213078.html

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

相关文章

浅聊汽车供应链数智化发展趋势

“2023中国汽车供应链大会暨第二届中国新能源智能网联汽车生态大会”在11月10日—12日&#xff0c;武汉经开区举办。围绕供应链安全与布局、新型汽车供应链打造、传统供应链升级、全球化发展等热点话题进行深入交流与探讨&#xff0c;寻找构建世界一流汽车供应链的对策、方法和…

华为ensp防火墙虚拟系统在网络中的部署

首先我们要知道虚拟系统是啥&#xff0c;干什么用的&#xff0c;解决什么问题的&#xff0c;说白话就是&#xff0c;我没钱&#xff0c;买不起两台墙&#xff0c;我买一台墙通过虚拟系统的方式逻辑变成两台墙&#xff0c;学过高级路由的都知道vpn&#xff0c;vpn是将路由器器逻…

算法学习打卡day45|动态规划:股票问题总结

Leetcode股票问题总结篇 动态规划的股票问题一共六道题&#xff0c;买卖股票最佳时机和买卖股票手续费都是一个类型的问题&#xff0c;维护好买入和卖出两个状态即可&#xff0c;方法一摸一样。而冷冻期也差不多就是状态多了点&#xff0c;买入、保持卖出、当日卖出、以及冷冻期…

黑马程序员微服务 第五天课程 分布式搜索引擎2

分布式搜索引擎02 在昨天的学习中&#xff0c;我们已经导入了大量数据到elasticsearch中&#xff0c;实现了elasticsearch的数据存储功能。但elasticsearch最擅长的还是搜索和数据分析。 所以今天&#xff0c;我们研究下elasticsearch的数据搜索功能。我们会分别使用DSL和Res…

《009.SpringBoot之汽车租赁系统》

《009.SpringBoot之汽车租赁系统》 项目简介 [1]本系统涉及到的技术主要如下&#xff1a; 推荐环境配置&#xff1a;DEA jdk1.8 Maven MySQL 前后端分离; 后台&#xff1a;SpringBootMybatisPlus; 前台&#xff1a;Layuivue; [2]功能模块展示&#xff1a; 前端门户 1.登录&a…

一键批量剪辑,创意黑白画面制作!

想要在视频画面上玩点新花样吗&#xff1f;想将你的视频制作成黑白画面风格吗&#xff1f;现在&#xff0c;我们为你带来了一款全新的批量剪辑工具&#xff0c;可以帮助你一键批量剪辑视频&#xff0c;并轻松制作出独特的黑白画面效果&#xff01; 第一步&#xff0c;我们要进…

代码安全之代码混淆及加固(Android)

​ 目录 代码安全之代码混淆及加固&#xff08;Android&#xff09;&#x1f512; 摘要 引言 正文 代码混淆 代码加固 总结 参考资料 摘要 本文将介绍如何通过代码混淆和加固来保护Android应用的代码安全性。代码混淆是将代码进行加密&#xff0c;使其难以被反编译获得…

【LeetCode:2656. K 个元素的最大和 | 贪心+等差数列】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

长安汽车基于 Apache Doris 的车联网数据分析平台建设实践

导读&#xff1a;随着消费者更安全、更舒适、更便捷的驾驶体验需求不断增长&#xff0c;汽车智能化已成必然趋势。长安汽车智能化研究院作为长安汽车集团有限责任公司旗下的研发机构&#xff0c;专注于汽车智能化技术的创新与研究。为满足各业务部门的数据分析需求&#xff0c;…

邮件钓鱼-邮件来源伪造-SPF绕过-setoolkitgohishswaks钓鱼

0x00 SPF简介 SPF即发送方策略框架&#xff0c;某种邮件服务器会有自己的SPF策略设定&#xff0c;可以设定SPF为只允许某些主机发送邮件等&#xff0c;当设定后第三方就无法伪造成邮件服务器的管理员对用户下发邮件。 是否存在SPF的验证&#xff1a; linux下&#xff1a;dig…

Servlet 常见的API

文章目录 写在前面Smart Tomcat 插件Servlet 中常见的API1. HttpServletinit 方法destroy 方法service 方法Servlet 的生命周期 使用 postman 构造请求使用 ajax 构造请求2. HttpServletRequest3. 前端给后端传参1). GET, query string2). POST, form3). json 4. HttpServletRe…

文件包含学习笔记总结

文件包含概述 ​ 程序开发人员通常会把可重复使用函数或语句写到单个文件中&#xff0c;形成“封装”。在使用某个功能的时候&#xff0c;直接调用此文件&#xff0c;无需再次编写&#xff0c;提高代码重用性&#xff0c;减少代码量。这种调用文件的过程通常称为包含。 ​ 程…

如何挑选护眼灯?光照均匀度、色温、眩光这3点!

光照环境对我们的生活质量影响深远&#xff0c;尤其在孩子的成长过程中&#xff0c;良好的光照环境对其学习效率、视力保护都至关重要。光照中的很多因素都对视力有着或大或小的影响&#xff0c;本文将从光照均匀度、眩光、色温三个关键点&#xff0c;深入浅出地让消费者了解其…

一键帮您解决win11最新版画图工具难用问题!

&#x1f984;个人主页:修修修也 ⚙️操作环境:Windows 11 正文 自从win11更新后,新版的画图工具变得非常难用,如: 使用橡皮擦后露出背版马赛克 框住某部分拖动移动时背景露出马赛克剪贴板上图片信息无法直接插入到画图板 目前没有一个好一些的能够在软件内部解决这些问题的方…

一家公司做了两年软件测试,只会功能测试,现在已经感到危机感了,那如何摆脱困境呢?

经常听到一些行业内的朋友说 “做测试&#xff0c;有手就行” 但事实真的是如此嘛&#xff1f; 随着测试行业的发展&#xff0c;越来越多的测试岗位对自动化测试&#xff0c;性能测试都有所要求&#xff0c;这对于很多只会功能测试的职场老人们来说&#xff0c;有了一丝丝的…

一个用于操作Excel文件的.NET开源库

推荐一个高性能、跨平台的操作Excel文件的.NET开源库。 01 项目简介 ClosedXML是一个.NET第三方开源库&#xff0c;支持读取、操作和写入Excel 2007 (.xlsx&#xff0c; .xlsm)文件&#xff0c;是基于OpenXML封装的&#xff0c;让开发人员无需了解OpenXML API底层API&#xf…

神经网络常见评价指标AUROC(AUC-ROC)、AUPR(AUC-PR)

神经网络的性能可以通过多个评价指标进行衡量&#xff0c;具体选择哪些指标取决于任务的性质。以下是神经网络中常见的评价指标&#xff1a; 准确性&#xff08;Accuracy&#xff09;&#xff1a; 准确性是最常见的分类任务评价指标&#xff0c;表示模型正确预测的样本数占总样…

从真实案例出发,全方位解读 NebulaGraph 中的执行计划

本文整理自 NebulaGraph 核心开发 Yee 在直播《聊聊执行计划这件事》中的主题分享。分享视频参见 B站&#xff1a;https://www.bilibili.com/video/BV1Cu4y1h7gn/ 一条 Query 的一生 在开始正式地解读执行计划之前&#xff0c;我们先来了解在 NebulaGraph 中&#xff0c;一条…

使用MathType将文献中的数学公式进行转换

mathtype将文献中的数学公式进行转换 文章目录 mathtype将文献中的数学公式进行转换一、截图识别二、MathType下载与设置2.1、MathType介绍2.2、[下载位置](http://www.51xiazai.cn/soft/5975.htm)2.3、设置 三、使用MathType&#xff1a; 一、截图识别 这两个在线网站都可以将…

【云栖2023】姜伟华:Hologres Serverless之路——揭秘弹性计算组

本文根据2023云栖大会演讲实录整理而成&#xff0c;演讲信息如下&#xff1a; 演讲人&#xff1a;姜伟华 | 阿里云计算平台事业部资深技术专家、阿里云实时数仓Hologres研发负责人 演讲主题&#xff1a;Hologres Serverless之路——揭秘弹性计算组 实时化成为了大数据平台的…