React 18:state概念与使用、注意问题

news2024/11/17 21:36:24

一、概念与基本使用

props中的所有属性都是不可变的,这使得React组件不能随着props的改变而改变。但在实际的开发中,我们更希望的是数据发生变化时,页面也会随着数据一起变化。React为我们提供了state用来解决这个问题。

state和props类似,都是一种存储属性的方式,但是不同点在于state只属于当前组件,其他组件无法访问。并且state是可变的,当其发生变化后组件会自动重新渲染,以使变化在页面中呈现。

在React中,当组件渲染完毕后,再修改组件中的变量,不会使组件重新渲染。
要使得组件可以收到变量的影响,必须在变量修改后对组件进行重新渲染。
这里我们就需要一个特殊变量,当这个变量被修改时,组件会自动重新渲染。

state相当于一个变量,
只是这个变量在React中进行了注册,
React会监控这个变量的变化,当state发生变化时,会自动触发组件的重新渲染
使得我们的修改可以在页面中呈现出来。

在函数组件中,我们需要通过钩子函数,获取state。

使用钩子 useState() 来创建state。

import {useState} from "react";

它需要一个值作为参数,这个值就是state的初始值
该函数会返回一个数组

  • 数组中第一个元素,是初始值
    初始值只用来显示数据,直接修改不会触发组件的重新渲染
  • 数组中的第二个元素,是一个函数,通常会命名为setXxx
    这个函数用来修改state,调用其修改state后会触发组件的重新渲染,并且使用函数中的值作为新的state值

现有如下组件Clock:

在这里插入图片描述
现在我们希望点击按钮以后,时间可以刷新直接显示一个当前的最新日期。希望页面重新渲染。但是,如果直接在clickHandler中修改date的值是无效的,像这样:

在这里插入图片描述

在这里插入图片描述

在函数中使用state我们需要使用一种钩子(hook)函数。钩子函数可以在函数组件中“勾出”React的特性,换句话说我们要用一个函数“勾出”state。

语法:

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

通过钩子函数useState()勾出state,useState()中需要传递一个初始值,这个值就是你希望在变量中存储的值。
函数会返回一个数组,数组中有两个元素,第一个元素是存储了值的变量,第二个元素是一个函数用来对值进行修改。
比如上边的案例,可以这样修改:
在这里插入图片描述
使用useState()“勾出”的变量就是一个普通变量,它里边存储了初始化的值,这个变量和其他变量没什么大区别,同样修改这个变量的值也不会对组件产生实质性的影响,所以不要尝试直接为state赋值。useState()“勾出”的函数用来修改state的值,他需要一个新的state值作为参数,调用后会触发组件的重新渲染,从而使得页面刷新,在每次的重新渲染中都会使用新的state值作为参数。

二、注意问题

引出问题

有了state,使得React组件可以随着某个值的改变而改变,我们无需再在某个值发生变化后重新手动对界面进行构建,React会替我们完成这些工作,大大降低了我们开发的难度。

但是state中还隐藏着一些不太容易发现的问题,现在假设我们需要开发一个计数器组件,这个组件非常简单,有一个按钮和一个数字,每点击一次按钮数字就会增加1,大概长成这个样子:
在这里插入图片描述

点击按钮以后,数字就会增加1,这个组件的实现很简单:

Counter.js
在这里插入图片描述

在clickHandler()中,我们调用了setCount(count+1)来对count进行更新,每次更新都是在前一次值的基础上增加1。这个代码这么写在大部分的场景下都不会带来任何的问题,但是在某些情况下就不一定了。

产生问题的原因

在React中我们通过setState()修改状态都是异步完成的,换句话说并不是调用完setState()后状态立刻就发生变化,而是需要等上一段时间,当然这段时间不会很长。
像上边的案例中state的修改虽然是异步完成的,但是由于功能比较简单,等待时间几乎可以忽略不计。但随着功能复杂度的提升,这个间隔会逐渐增多。

问题演示

假设调用setState()后1秒state的值才会真的改变,这时如果我们连续点击按钮2次,第1次点击按钮时count值是1,第2次点击速度比较快,从而两次间隔没有超过1秒,此时的count值依然是1,这就导致我点击了两次按钮,但是值只增加了1次,因为两次count+1中的count都是1。

为了演示问题,可以将上述案例的setCount()放入到一个延时调用中:
在这里插入图片描述
这样一来,点击按钮后1秒setCount()才会调用,如果我们在1秒内点击按钮多次,你会发现按钮数值只会增加一次,很显然我们不希望这种情况出现。

解决问题

要解决这个问题,其实也不难,在setState()时除了直接传递一个指定值以外,React还允许我们通过一个回调函数来修改state,回调函数的返回值就是新的state的值,使用回调函数的好处是,这个回调函数会确保上一次的setState()调用完成后才被调用,同时会使用最新的state值作为回调函数的第一个参数。这样一来就有效的避免了无法正确获取上一个state值的问题。

上边案例中的 setCount(count+1);可以改成这个样子:

setCount(prevState => prevState+1);

在这里插入图片描述
这样一来,函数中的prevState总是上次修改后的最新state,避免再次出现点击多次按钮只修改一次的问题。总的来说,当我们修改一个state的值而需要依赖于前边的值进行计算时,最安全的方式就是通过回调函数而不是直接修改。

在这里插入图片描述

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

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

相关文章

类的赋值与浅拷贝

类的浅拷贝与深拷贝 变量的赋值操作 只是形成两个变量,实际上还是指向同一个对象浅拷贝 Python拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝因此,源对象与拷贝对象会引用同一个子对象深拷贝 使用copy模块的deepcopy函数…

[附源码]JAVA毕业设计疫情防控期间网上教学管理(系统+LW)

[附源码]JAVA毕业设计疫情防控期间网上教学管理(系统LW) 项目运行 环境项配置: Jdk1.8 Tomcat8.5 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 …

window下生成SANs证书给ingress用

1.安装openssl openssl下载地址:http://slproweb.com/products/Win32OpenSSL.html http://slproweb.com/products/Win32OpenSSL.html 下载指定版本exe安装。 2. 修改openssl配置 为了方便我们copy一份openssl.cfg,用来修改 C:\Users\vamcl\Deskto…

做自媒体18个月,倒欠38万,一个自媒体创作者的自述

做自媒体18个月,倒欠38万,一个自媒体创作者的自述 疫情开始后,长期居家,工作和生活都受到了明显影响,偶然在网上看到了自媒体这个行业,号称日入几千几万。 前前后后花非不少钱买设备、买课、买会员等等,花费近40w颗粒…

Java网络编程,超详细

计算机网络分为网络协议和网络体系结构 通过网络发送数据是一项复杂的操作,必须仔细地协调网络的物理特性以及所发送数据的逻辑特征。通过网络将数据从一台主机发送到另外的主机,这个过程是通过计算机网络通信来完成。 网络通信的不同方面被分解为多个…

爆火的OpenAI及ChatGPT注册详细说明

1 准备条件 ① 需要梯子 ② 准备一个能够接收openai的手机号,用于接收注册验证码 (如果没有也不要紧,下面会介绍通过第三方接码平台来注册) 2 注册手机号接收验证码 网址:https://sms-activate.org/cn/getNumber 2.1 点击右上角注册 这里…

在word表格中一键生成序号,如何操作?

在word表格中一键生成序号,如何操作? 目录 在word表格中一键生成序号,如何操作? 1、首先选中需要填序号的这一列​ 2、在【开始】菜单中找到【多级列表】点击,再点击【定义新的多级列表】​ 3、点击【修改级别中的1…

ELK企业级日志收集

目录 一、ELK简介 二、ELK各组件介绍 ElasticSearch: Kibana: Logstash: 三、ELK可以添加的其他组件 Filebeat: 缓存/消息队列(redis、kafka、RabbitMQ等): Fluentd: 四、为…

【C初阶】第五篇——数组

一维数组的创建和初始化 数组的创建 数组的初始化 一维数组的使用 一维数组在内存中的存储 二维数组的创建和初始化 二维数组的创建 二维数组的初始化 二维数组的使用 二维数组在内存中的存储 数组越界 数组作为函数参数 冒泡排序函数的错误设计 数组名是什么? …

[附源码]Python计算机毕业设计SSM基于的汉服服装租赁系统(程序+LW)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

[附源码]Python计算机毕业设计Django大学生志愿者服务管理系统

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…

配置vue3适用的vue-devtools

1、下载最新的vue/devtools的github项目库 项目库地址为 :GitHub - vuejs/devtools: ⚙️ Browser devtools extension for debugging Vue.js applications. 2、安装yarn vue/devtools的项目库,必须使用yarn来编译,npm会报错。 npm i 会报…

SQLyog Ultimate最流行的数据库管理工具之一

SQLyog Ultimate最流行的数据库管理工具之一 SQLyog是为Windows提供的最流行的SQL数据库管理工具之一。该软件是世界上任何地方的数据库管理工具,非常快速,易于使用和维护图形环境。使用此程序,您可以构建漂亮的数据,并在可视摄像…

Java教程-特性/语法/对象和类/基本数据类型/变量修饰符运算符/循环结构和条件语句/数组/正则/文件IO/异常处理详细总结

文章目录教程简介主要特性Java 语言是简单的:Java 语言是面向对象的:Java语言是分布式的:Java 语言是健壮的:Java语言是安全的:Java 语言是体系结构中立的:Java 语言是可移植的:Java 语言是解释…

stm32 如何查看系统各个时钟

在主函数main中会通过定义SystemInit()函数中设置的系统时钟大小: SYSCLK(系统时钟) 72MHz AHB 总线时钟(使用 SYSCLK) 72MHz APB1 总线时钟(PCLK1) 36MHz APB2 总线时钟(PCLK2) 72MH…

消息队列---MQ介绍

文章目录前言一、MQ是什么?1.1基本概念1.2MQ的优势和劣势优势应用解耦异步提速削峰填谷劣势二、常见的MQ产品总结前言 实习之MQ学习历程 一、MQ是什么? 1.1基本概念 MQ全称Message Queue(消息队列),是在消息的传输过程中保存消息的容器。多用于分布式系…

【数据结构】堆排序 (超详细)

前言:      前几次讲了如何构建一个堆以及TopK算法,那么这次给大家分享一下堆排序的两种方法。 方法一 直接暴力解决,建一个小堆,把数组的数据依次push,随后每次Pop堆顶,放进数组里。不过该方法因为建堆有消耗&…

字体图标、平面转换、渐变

1、字体图标 字体图标 字体图标展示的是图标,本质是字体。处理简单的、颜色单一的图片 1.1、字体图标的优点: 灵活性:灵活地修改样式,例如:尺寸、颜色等轻量级:体积小、渲染快、降低服务器请求次数兼容性…

SQL ALTER TABLE 语句

📒博客主页: ​​开心档博客主页​​ 🎉欢迎关注🔎点赞👍收藏⭐留言📝 📌本文由开心档原创! 📆51CTO首发时间:🌴2022年12月12日🌴 ✉…

华硕编程竞赛11月JAVA专场 J题再见天空 题解

作者主页:Designer 小郑 作者简介:Java全栈软件工程师一枚,来自浙江宁波,负责开发管理公司OA项目,专注软件前后端开发(Vue、SpringBoot和微信小程序)、系统定制、远程技术指导。CSDN学院、蓝桥云…