React hooks(一):useState

1.React hooks

React hooks是React16.8的新特性,可以让React函数组件具有状态,并提供类似componentDidMount和componentDidUpdate等生命周期方法。

React 早期版本,类组件可以在shouldComponentUpdate中,通过判断props和state是否发生变化来决定需不需要重新渲染组件。而继承PureComponent后,当组件更新时,如果组件的 props 和 state 都没发生改变, render 方法就不会触发,省去 Virtual DOM 的生成和比对过程,达到提升性能的目的。具体就是 React 自动在shouldComponentUpdate中帮我们做了一层浅比较。这样我们可以少写 shouldComponentUpdate 函数。相对于函数组件,我们知道函数每次调用,就会执行函数体,然而React 官网没有提供对应的方法来缓存函数组件以减少一些不必要的渲染,直到 16.6 出来的 React.memo函数。

React 16.8 新出来的Hooks可以让React 函数组件具有状态,并提供类似 componentDidMount和componentDidUpdate等生命周期方法。

Hook 这个单词的意思是"钩子"。

React Hooks 的意思是,组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码"钩"进来。 React Hooks 就是那些钩子。

你需要什么功能,就使用什么钩子。React 默认提供了一些常用钩子,你也可以封装自己的钩子。

所有的钩子都是为函数引入外部功能,所以 React 约定,钩子一律使用use前缀命名,便于识别。你要使用 xxx 功能,钩子就命名为 usexxx。

2.useState

鉴于纯函数自身无法保存状态,要在两次组件函数执行期间保存和修改状态,必须引入副作用,使用外部存储能力,所以引入了useState。

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

其中,初始化参数initialState可以试一个值,也可以是一个函数。如果传递函数作为 initialState,则它将被视为 初始化函数。它应该是纯函数,不应该接受任何参数,并且应该返回一个任何类型的值。当初始化组件时,React 将调用你的初始化函数,并将其返回值存储为初始状态。

set函数的参数可以是一个值nextState,也可以是一个函数。如果你将函数作为 nextState 传递,它将被视为 更新函数。它必须是纯函数,只接受待定的 state 作为其唯一参数,并应返回下一个状态。React 将把你的更新函数放入队列中并重新渲染组件。在下一次渲染期间,React 将通过把队列中所有更新函数应用于先前的状态来计算下一个状态。

2.1 必须组件的顶层调用

第一个关键点:useState 是一个 Hook,因此你只能在 组件的顶层 或自己的 Hook 中调用它。你不能在循环或条件语句中调用它。如果你需要这样做,请提取一个新组件并将状态移入其中。

因为 hooks 为了在函数组件中引入状态,维护了一个有序表。

比如第一次执行函数组件时,我们拿到状态 count(通过useState,初始值为 0 )和 bool(通过 useState,初始值为 false),它们其实被保存到一个有序表中,它们的值会记录下来: [0, false]。

第二次执行函数组件, 会 按顺序 从这个表中拿出 0 和false,赋值给 count 和 bool。

如果你把 hook 写到判断条件下,导致某个 useState 不执行了,这里我们假设 count 的 useState 因为判断条件没有执行,会发生什么?结果是 bool 拿到了 0,发生了错位。

函数本身不能保存状态,我们需要额外维护一个有序的表,在执行 useState 之类的 hook 时,将它们保存到这个表里。

这要求每次函数组件的 hook 执行的位置相同,数量正确,否则会导致错位,不能拿到预期的状态值。

2.2 严格模式下的多次执行

第二个关键点:在严格模式中,React 将 两次调用组件函数、初始化函数和更新函数,以 帮你找到意外的不纯性。这只是开发时的行为,不影响生产。如果你的初始化函数是纯函数(本该是这样),就不应影响该行为。其中一个调用的结果将被忽略。

调用setState只会将更新函数放入队列,并不会立即修改当前的state,直到下次渲染的时候,state才会修改为更新后的值。那么如果你的setState是纯函数,在两次渲染之间无论执行多少次,都会有相同的state。反之,如果你的setState不纯,直接修改了当前的state,那么多次执行后的结果都不同。React使用Object.is 比较两个state是否相同。

下面是一个纯函数的例子:

function TodoList() {// 该函数组件会在每次渲染运行两次。const [todos, setTodos] = useState(() => {// 该初始化函数在初始化期间会运行两次。return createTodos();});function handleClick() {setTodos(prevTodos => {// 该更新函数在每次点击中都会运行两次return [...prevTodos, createTodo()];});}// ...

更新函数不纯的例子:

setTodos(prevTodos => {// 🚩 错误:改变 stateprevTodos.push(createTodo());
});

参考:

useState – React 中文文档

为什么 hooks 不能写在循环或者条件判断语句里_hooks为什么不能写在条件语句中-CSDN博客

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

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

相关文章

搭建yum源并定时同步

一 、安装yum源 1-准备yum目录 cd /data/www/html createrepo -v ./目录 2-安装服务 yum -y install httpd 3-配置服务 /etc/httpd/conf/httpd.conf 4.配置/etc/yum.repo.d/local.rpeo 二、定时更新yum源 #1. 同步整个源到指定目录 [rootV10SP1-1 pac]# reposync -p /root/…

到底什么是Linux?快进来学习!

相信大家对Linux并不陌生吧?Linux 是一种计算机系统,属于基础中的基础,就和我们熟知的Windows一样,都是系统。它是现今最流行和最实用的计算机操作系统,它区别于后台、算法、大数据、前端、测试方向,需要程…

python 随机数生成

生成随机整数 使用 randint() 函数可以生成指定范围内的随机整数。 import random # 生成1到10之间的随机整数 random_int random.randint(1, 10) print(random_int) 生成随机浮点数 random() 方法用于生成 0 到 1 之间的随机浮点数。 import random # 生成0到1之间…

LVGL 日历组件

LVGL 日历组件 calendar 添加到默认组中 lvgl的 calendar 组件会默认添加到旋钮按键组中,需要手动将其删除,否则会聚焦到不可见的控件上。 lv_obj_set_style_pad_all(calendar, 8, LV_STATE_DEFAULT); lv_group_remove_obj(calendar);修改时间范围 年…

[msg_msg] corCTF2021 -- fire_of_salvation

前言 msg_msg 是 kernel pwn 中经常用作堆喷的结构体. 其包含一个 0x30 大小的 header. 但 msg_msg 的威力远不如此, 利用 msg_msg 配合其他堆漏洞可以实现任意地址读写的功能. 程序分析 本题给了源码, 可以直接对着源码看. 并且题目给了编译配置文件, 所以可以直接编译一个…

C++ const与符号表

fun_cpp.cpp //const修饰的全局变量 默认是内部链接(只在当前源文件有效 不能直接用于其他源文件) const int num_pp 100;//如果必须用在其他源文件 使用只读的全局变量 必须加extern将num转换成外部链接 //extern const int num_pp 100;main_cpp.cpp…

Linux/麒麟系统上部署Vue+SpringBoot前后端分离项目

目录 1. 前端准备工作 1.1 在项目根目录创建两份环境配置文件 1.2 环境配置 2. 后端准备工作 2.1 在项目resources目录创建两份环境配置文件 2.2 环境配置 3. 前后端打包 3.1 前端打包 3.2 后端打包 4、服务器前后端配置及部署 4.1 下载、安装、启动Nginx 4.2 前端项目部署…

Elasticsearch搜索分析引擎本地部署与远程访问

文章目录 系统环境1. Windows 安装Elasticsearch2. 本地访问Elasticsearch3. Windows 安装 Cpolar4. 创建Elasticsearch公网访问地址5. 远程访问Elasticsearch6. 设置固定二级子域名 Elasticsearch是一个基于Lucene库的分布式搜索和分析引擎,它提供了一个分布式、多…

【小白的Spring源码手册】 BeanFactoryPostProcessor的注册和用法(BFPP)

目录 前言应用1. 手动注册2. 自动注册3. 优先级 前言 沿用上一篇文章的流程图,我们的注解类应用上下文中的AnnotationConfigApplicationContext#scan(String...)方法已经将所有BeanDefinition注册到了IoC容器中。完成注册后,开始执行AbstractApplicatio…

信息的浏览

万维网(WWW)是目前Internet上最流行的一种服务,它是建立在Internet上的多媒体集合信息系统。它利用超媒体的信息获取技术,通过一种超文本的表达方式,将所有WWW上的信息连接在一起。我们使用浏览器浏览网上的信息。 ▶浏览器 浏览器是指可以…

PHP低版本安全问题

目录 1、PHP弱类型问题 1.1 MD5、 SHA1 弱比较问题 1.2 数组 0 1)函数无法处理数组,返回0 2)strcmp 2、特殊字符串导致的问题 2.1 "ffifdyop" 与 md5(string,raw) 2.2 ereg函数漏洞:00 截断 3、正则匹配问…

物联网AI MicroPython学习之语法UART通用异步通信

学物联网,来万物简单IoT物联网!! UART 介绍 模块功能: UART通过串行异步收发通信 接口说明 UART - 构建UART对象 函数原型:UART(id, baudrate,bits, parity,stop, tx, rx)参数说明: 参数类…

3GPP协议解读(一)_23.501_23.502_PDU Session_SMF与UDP的交互

UE发起计算服务申请后,网络侧处理的流程 UE发起服务的流程:service request网络侧处理服务涉及的通信数据通过PDU Session进行传输,涉及到SMF与UPF的交互。PDU Session的建立、管理全部由SMF(Session Management Function&#x…

Git通过rebase合并多个commit

在使用 Git 作为版本控制的时候,我们可能会由于各种各样的原因提交了许多临时的 commit,而这些 commit 拼接起来才是完整的任务。那么我们为了避免太多的 commit 而造成版本控制的混乱,通常我们推荐将这些 commit 合并成一个。 1. 查看提交历…

基于JavaWeb+SpringBoot+掌上社区疫苗微信小程序系统的设计和实现

基于JavaWebSpringBoot掌上社区疫苗微信小程序系统的设计和实现 源码获取入口前言主要技术系统设计功能截图Lun文目录订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种…

2. zk集群部署

简介 上一篇文章我们已经把环境准备好了,jdk也配置好了,下面我们开始把zk部署起来 hadoop环境准备 创建zk用户 useradd zk -d /home/zk echo "1q1w1e1r" | passwd --stdin zk上传zk包 拷贝zk包到/home/zk目录,这里的zk版本为 3.6.3 scp…

windows使用lcx端口转发登陆远程主机

1.编译lcx源码: GitHub - UndefinedIdentifier/LCX: 自修改免杀lcx端口转发工具 2.在win7上安装vs2010并编译生成lcx.exe 3.在要被控制主机上运行: lcx -slave 192.168.31.248 51 192.168.31.211 3389 192.168.31.248为远程主控制主机,51为远程主机端口 192.168.31.211为被…

Java笔试题

5.18:JAVA面试题 Java笔试题目及答案

C语言--写一个函数返回bool值,来判断给定的字符串A和B(假设都是小写字母),是否是B中的字符都存在于A中,如果是返回true,否则返回false

一.题目描述 写一个函数返回bool值,来判断给定的字符串A和B(假设都是小写字母),是否是B中的字符都存在于A中,如果是返回true,否则返回false。例如: 字符串A:abcde 字符串B&#xff…

顶部动态菜单栏的使用

效果图 开发环境 vue3 关键逻辑 //导航栏状态选择 const navbarSolid ref(false); //初始化导航栏高度 const navbarHeight ref(0);/*** 根据滚动距离改变样式*/ function checkNavbarOpacity() {navbarSolid.value window.pageYOffset > navbarHeight.value / 2; }/**…