文章目录

  • 一文讲清楚React中setState的使用方法和机制
  • 1. setState是什么
  • 2. setState方法详解
    • 2.1 setState参数详解
    • 2.2 setState同步异步问题
      • 2.2.1 setState异步更新
      • 2.2.2 setState同步更新

一文讲清楚React中setState的使用方法和机制

1. setState是什么

  • React中,this.setState(updater,callback)是一个方法,用来改变state的值,进而实现页面的重新渲染
  • 不了解的先看这篇文章一文讲清楚React中state和props的区别与联系
  • 直接上例子
import React from 'react'
class App extends React.Component{constructor(props){super(props)this.state={name:'tom'}}handleClick=()=>{this.setState({name:'new tom'})}render(){return(<div><div>{this.state.name}</div><button onClick={this.handleClick}>change name in by setState</button></div>)}
}
export default App
  • 运行显示tom,点击按钮通过setState方法把name改为new tom,发现页面显示成了new tom

2. setState方法详解

2.1 setState参数详解

  • setState由两个参数,updater和callback,updater可以是对象也可以是函数
  • 我们下一个计数器的demo
import React from 'react'
class App extends React.Component{constructor(props){super(props)this.state={count:0}}handleClick=()=>{this.setState(preState=>({count:preState.count+1}))}render(){return(<div><div>{this.state.count}</div><button onClick={this.handleClick}>+1</button></div>)}
}
export default App
  • 点击+1,也能实现状态的改变并现实出来
  • 那么对象参数和函数参数有什么区别呢,先给出答案,如果是参数是对象,会进行事件合并,如果参数是函数,不会发生事件合并,上代码
  • 我们设置两个计数器,一个从参数对象更新,一个用参数函数更新,每点击一次按钮,计数器做三次+1操作
import React from 'react'
class App extends React.Component{constructor(props){super(props)this.state={count1:0,count2:0,}}handleClick=()=>{//第一个计数器用对象参数执行三次+1this.setState({count1:this.count1+1})this.setState({count1:this.count1+1})this.setState({count1:this.count1+1})//第2个计数器用函数参数执行三次+1this.setState(preState=>({count2:preState.count2+1}))this.setState(preState=>({count2:preState.count2+1}))this.setState(preState=>({count2:preState.count2+1}))}render(){return(<div><div>count1:{this.state.count1}</div><div>count2:{this.state.count2}</div><button onClick={this.handleClick}>+1</button></div>)}
}
export default App
  • 运行
    在这里插入图片描述

  • 初始值都是0没问题

  • 然后点按钮
    在这里插入图片描述

  • 会发现count1只+1,而count2+3,这是因为setState在参数为对象的模式下,对批量操作会进行覆盖,只取最后一次结果执行

  • setState还有第二个参数,callback,我们在下面讲

2.2 setState同步异步问题

2.2.1 setState异步更新

  • 先直接上代码
import React from 'react'
class App extends React.Component{constructor(props){super(props)this.state={count:0}}handleClick=()=>{this.setState(preState=>({count:preState.count+1}))console.log(this.state.count)}render(){return(<div><div>{this.state.count}</div><button onClick={this.handleClick}>+1</button></div>)}
}
export default App
  • 运行,处置为.,然后点击+1按钮,发现页面显示1,但是console.log打印0
    在这里插入图片描述

  • 这是为什么呢,这是因为React在合成事件中,state是异步更新的

  • 为什么会是一步的呢,问题就出现在合成事件上,不懂合成事件的看这篇文章一文讲清楚React合成事件机制和this的绑定问题

  • 因为合成事件的原因,console.log的执行时机别state更新的时机要早,所以造成了异步现象

  • 同理,在生命周期函数中改变状态也会造成异步更新

  • 如果想要拿到更新后的state,就需要setState第二个参数callback,他会在UI更新后被调用

  • 我们这么改一下代码

import React from 'react'
class App extends React.Component{constructor(props){super(props)this.state={count:0}}handleClick=()=>{this.setState(preState=>({count:preState.count+1}),()=>{console.log(this.state.count)})}render(){return(<div><div>{this.state.count}</div><button onClick={this.handleClick}>+1</button></div>)}
}
export default App
  • 这时候我们拿到了同步的值
    在这里插入图片描述

2.2.2 setState同步更新

  • 上面说因合成事件会导致异步更新,那如果我们使用原生事件呢,上代码
import React from 'react'
class App extends React.Component{constructor(props){super(props)this.state={count:0}}componentDidMount(){document.getElementById('update').addEventListener('click',this.handleClick)}handleClick=()=>{this.setState(preState=>({count:preState.count+1}))console.log(this.state.count)}render(){return(<div><div>{this.state.count}</div><button id="update">+1</button></div>)}
}
export default App
  • 运行会发现,还是打印0,哈哈哈,那是因为React在V16版本前,在原生事件和setTimeout中setState是同步事件,这里本来想演示这个来着,但是奈何坐着的React的版本比较高,这里建议大家切换低版本自己运行一下,代码肯定是没有任何问题的
  • React为了让setState在所有场景下保持一致性,从V16+开始,无论是合成事件、原生事件还是setTimeout都是保持异步,要获取更新后的状态请统一使用setState第二个回调函数

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

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

相关文章

01_软件卓越之道:功能性与需求满足

引言 在软件的世界里&#xff0c;功能性是产品与用户之间的第一桥梁。一个软件即使拥有华丽的界面和极致的性能&#xff0c;如果不能解决用户的核心需求&#xff0c;也终将被市场淘汰。本文将深入探讨如何确保软件的功能性与用户需求完美契合。 1. 需求理解&#xff1a;从模糊…

StarRocks × Tableau 连接器完整使用指南 | 高效数据分析从连接开始

一、导语&#xff1a;为什么选择 StarRocks Tableau 连接器&#xff1f; 在当今数据驱动的商业环境中&#xff0c;企业不仅需要一个能够处理海量数据的高性能分析数据库&#xff0c;还需要一个直观、强大的可视化工具来解读数据背后的故事。StarRocks 作为新一代极速全场景 MP…

基于 SpringBoot+VueJS 助农生鲜销售系统设计与实现7000字论文实现

摘要本论文设计并实现了一个基于 SpringBoot 和 VueJS 的助农生鲜销售系统。系统采用前后端分离架构&#xff0c;前端使用 VueJS 框架实现用户界面&#xff0c;后端使用 SpringBoot 框架构建服务&#xff0c;通过 MyBatis 实现数据持久化。系统实现了农产品展示、在线购物、订单…

Pytest 测试发现机制详解:自动识别测试函数与模块

概述 在编写自动化测试时,如何让 Pytest 自动找到你的测试代码 是一个非常基础但重要的问题。Pytest 通过其强大的 测试发现(Test Discovery)机制,能够自动扫描项目目录、识别测试模块和测试函数,从而大大简化了测试流程。 本文将为你详细讲解 Pytest 的测试发现机制,包…

MySQL 时间日期函数

时间日期类型 MySQL中主要支持以下几种时间日期类型&#xff1a; DATE - 日期类型 格式&#xff1a;YYYY-MM-DD范围&#xff1a;1000-01-01 到 9999-12-31示例&#xff1a;2023-05-20 TIME - 时间类型 格式&#xff1a;HH:MM:SS范围&#xff1a;-838:59:59 到 838:59:59示例&…

408第三季part2 - 计算机网络 - 物理层

理解 这里有8个波形&#xff0c;每个波形代表一个马原&#xff0c;一个马原代表多个比特&#xff0c;这里3个比特 求波特率就直接2W 求比特率就要乘log2V 这块记两公式就行&#xff0c;一个下面一个上面 题目 4个相位加4种幅度就是有16种波形 这里无噪声就是奈奎斯特定理 这…

iOS 集成RN Installing glog (0.3.5)报错的解决方案

在集成执行RN bundle exec pod install 命令到Installing glog (0.3.5)时报错,报错信息如下: Installing glog (0.3.5) [!] /bin/bash -c set -e #!/bin/bash # Copyright (c) Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license …

【进阶篇-消息队列】——MQTT协议如何支持海量的在线IoT设备

目录 一、什么是IoT二、MQTT 和其他消息队列的传输协议有什么不同三、如何选择 MQTT 产品四、MQTT 集群如何支持海量在线的 IoT 设备五、总结本文来源:极客时间vip课程笔记 一、什么是IoT IoT,也就是物联网,物联网这个词儿,它的含义还不那么直观,但你看它的英文:IoT,也就…

Chat Model API

聊天模型API为开发人员提供了将人工智能聊天完成功能集成到应用程序中的能力。它利用预训练的语言模型&#xff0c;如GPT&#xff08;生成预训练转换器&#xff09;&#xff0c;以自然语言对用户输入生成类似人类的响应。 API通常通过向人工智能模型发送提示或部分对话来工作&…

【黑群晖】自组硬件/旧电脑nas改造(三)——使用Jellyfin创建家庭影音库

一、打开套件中心安装Jellyfin套件 如果找不到Jellyfin套件&#xff0c;需要手动添加三方套件源&#xff1a; 《群晖NAS必学技能&#xff1a;一键解锁三方套件源&#xff0c;PT下载影音播放全搞定&#xff01;》 二、配置Jellyfin 访问http://群晖IP:8096 进入Jellyfin初始化界…

泰山派编译debian报错 lb config: unrecognized option ‘--debootstrap-options‘

简介 最近在编译泰山派 编译buildroot系统正常&#xff0c;但是编译debian时总是报错说lb 找不到一些参数&#xff0c;如下图所示&#xff0c;应该当前的版本较低 不支持这些参数&#xff0c;我试了很多方法 升级次版本 但是提示的是最新的&#xff0c;最后经过一番搜索 在官方…

跨境证券交易系统合规升级白皮书:全链路微秒风控+开源替代,护航7月程序化交易新规落地

1 行业变革&#xff1a;四重驱动力重塑证券交易系统 当前全球证券行业正处于深刻变革期&#xff0c;跨境金融活动面临前所未有的机遇与挑战。今日央行开展的1310亿元7天期逆回购操作&#xff0c;以及国家外汇管理局向合格境内机构投资者(QDII)新增发放30.8亿美元投资额度等政策…

Node.js核心API(fs篇)

前言&#xff1a;在Node.js生态系统中&#xff0c;文件系统操作是后端开发不可或缺的一部分。fs模块作为Node.js核心API的重要组成部分&#xff0c;提供了与文件系统交互的能力&#xff0c;涵盖了从基础的文件读写到复杂的目录操作等功能。现代JavaScript开发中&#xff0c;处理…

HarmonyOS学习2---Stage模型

1、工程目录结构 1.1、入口 UIAbility 1.2、入口page 1.3、配置文件 1、配置文件 1&#xff09;应用级配置文件 --- app.json5 2&#xff09;模块级配置文件 --- module.json5 3、oh-package.json5 4、资源文件 1&#xff09;element目录 2&#xff09;media目录 3&#xff09…

【软件工程】软件复刻项目的完整流程指南

软件复刻项目的完整流程指南 第一章、概述 一、前期准备&#xff1a;明确目标与合规性 1. 法律风险评估 版权排查&#xff1a;确认目标软件的 UI 设计、代码、商标是否受保护&#xff08;如界面元素、核心算法是否申请专利&#xff09;。规避侵权&#xff1a;避免直接复制 …

浅谈Python 中的当前工作目录与脚本目录

Python 中的 os.path.exists() 和 __file__ 使用陷阱&#xff1a;工作目录 ≠ 脚本目录 在使用 os.path.exists() 或 open() 等函数操作文件路径时&#xff0c;笔者常常忽略一个关键概念&#xff1a;当前运行目录&#xff08;Current Working Directory, CWD&#xff09;并不等…

iOS检测并阻止骚扰电话的方法

检测并阻止骚扰电话 你可以在 iPhone 上使用“将未知来电者设置为静音”或第三方 App 来阻止骚扰电话。 打开“将未知来电者设置为静音” 在 iOS 13 及更高版本中&#xff0c;你可以打开“静音未知来电”&#xff0c;以免接到陌生人的来电。这一功能可以阻止那些你从未联系过…

TensorFlow源码深度阅读指南

TensorFlow源码深度阅读指南 本文基于《TensorFlow内核剖析》附录A的代码阅读方法论&#xff0c;结合实例解析核心源码阅读技巧&#xff08;含关键图示&#xff09;&#xff1a;一、源码阅读的四个维度 1. 分层切入策略&#xff08;图A-1&#xff09; #mermaid-svg-ooLMzaWU5ky…

设计模式-责任链模式、策略模式

责任链模式 Chain of Responsibility&#xff08;职责链&#xff09;—对象行为型模式定义&#xff1a;使多个对象都有机会处理请求&#xff0c;从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链&#xff0c;并沿着这条链传递该请求&#xff0c;直到有对象…

泛微e-cology remarkOperate远程命令执行漏洞

【高危】泛微e-cology remarkOperate远程命令执行漏洞 漏洞描述 泛微e-cology是泛微公司开发的协同管理应用平台。 受影响版本中&#xff0c;接口 /api/workflow/reqform/remarkOperate 存在 SQL 注入漏洞&#xff0c;multipart 类型参数 requestid 直接拼接进 SQL 语句&…