你真的了解react中的setState吗?(setState现象及原理全方位解析)

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 在刚开始学习react的时候,我们会经常使用到setState改变状态,既然用的多,那么就应该思考:为什么要使用setState?setState是'异步'的吗?本篇文章就围绕着这两个问题展开

前言

在刚开始学习react的时候,我们会经常使用到setState改变状态,既然用的多,那么就应该思考:==为什么要使用setState?== ==setState是'异步'的吗?== 本篇文章就围绕着这两个问题展开

为什么要使用setState?

先来看一个简单的setState例子:
这是一个比较基础的例子,点击按钮改变state中msg的值

import React, { Component } from 'react'

export class App extends Component {
    state = {
        msg: 'hello world'
    }
    render() {
        return (
            <div>App
                <h2>{this.state.msg}</h2>
                <button onClick={this.change}>change</button>
            </div>
        )
    }
    // setState继承自Component
    change = () => {
        this.setState({msg: 'haha'})
    }
}

export default App

==那么我们为什么要使用setState?==
因为我们修改了状态state的时候,希望React根据最新的state来重新渲染界面,直接修改的方式,react并不会知道状态发生了改变。
react没有实现类似于Vue2中Object.defineProperty或者是Vue3 proxy的方式来监听数据的变化,必须通过setState来告知react状态的改变。
setState是继承自Component,当我们调用setState的时候,会重新执行render方法。

setState是'异步'的吗

对于这个问题,还是用以下不同情形的例子来进行解答:

例一:生命周期函数中使用

1.在componentDidMount函数中使用 this.setState赋值,并在它和componentDidUpdate函数中进行打印

import React, { Component } from 'react'

export class App extends Component {
    state = {
        count: 0
    }
    componentDidMount() {
        this.setState({count: 1})
        console.log(this.state.count) // 0
    }
    componentDidUpdate() {
        console.log(this.state.count) // 1
    }
    render() {
        return (
            <div></div>
        )
    }
    // setState继承自Component
    change = () => {
        this.setState({msg: 'haha'})
    }
}

export default App

查看结果,componentDidUpdate函数中打印0,componentDidUpdate函数打印1,这说明setState在生命周期是异步的

来看下一个例子

例二:在合成事件中使用

2.点击按钮触发change事件,事件中使用this.setState修改state中count的值,并打印this.state.count

import React, { Component } from 'react'
// 在合成事件里,setState是异步的
export class App extends Component {
    state = {
        count: 0
    }
    render() {
        return (
            <div>App
                <h2>{this.state.count}</h2>
                {/* 这个就是合成事件 */}
                <button onClick={this.change}>change</button>
            </div>
        )
    }
    // setState继承自Component
    change = () => {
        this.setState({count: 1})
        console.log(this.state.count) // 0
     
    }
}

export default App

运行查看结果
在这里插入图片描述
这里点击了按钮,上面数据已经更改为1了,但是控制台打印的却是9,这是为何呢?
==理论来讲执行代码的过程是同步的,从上往下。出现异步的结果是因为合成事件和生命周期中,调用顺序是在更新之前,所以导致我们没有办法立即拿到更新后的值所以才形成了所谓的异步现象。这里说的异步并不是指内部由异步代码实现的==

例三:在setTimeout中使用

3.写一个定时器的例子,在里面使用this.setState修改值并打印:

import React, { Component } from 'react'
export class App extends Component {
    state = {
        count: 0
    }
    componentDidMount() {
        setTimeout(() => {
            this.setState({count: 1})
            console.log(this.state.count) // 1
        }, 0)
    }
    render() {
        return (
            <div>App
                <h2>{this.state.count}</h2>
            </div>
        )
    }
}

export default App

查看结果发现打印的是1,说明setTimeout里setState是同步的

例四:在原生事件中使用

  1. 再来一个原生事件的例子,点击按钮触发click,更改数据并且打印:
import React, { Component } from 'react'
// 在原生事件中是同步的
export class App extends Component {
    state = {
        count: 0
    }
    componentDidMount() {
        document.querySelector('button').addEventListener(
            'click',
            (e) => {
                this.click()
            },
            false
        )
    }
    click() {
        this.setState({count: 1})
        console.log(this.state.count)  // 1
    }
    render() {
        return (
            <div>App
                <h2>{this.state.count}</h2>
                <button>按钮</button>
            </div>
        )
    }
}

export default App

最后的运行结果为1,说明在原生事件中是同步的

总结:

setState在生命周期和合成事件里面是异步的,在setTimeout和原生事件中是同步的

相关文章
|
14天前
|
安全 算法 网络协议
解析:HTTPS通过SSL/TLS证书加密的原理与逻辑
HTTPS通过SSL/TLS证书加密,结合对称与非对称加密及数字证书验证实现安全通信。首先,服务器发送含公钥的数字证书,客户端验证其合法性后生成随机数并用公钥加密发送给服务器,双方据此生成相同的对称密钥。后续通信使用对称加密确保高效性和安全性。同时,数字证书验证服务器身份,防止中间人攻击;哈希算法和数字签名确保数据完整性,防止篡改。整个流程保障了身份认证、数据加密和完整性保护。
|
6天前
|
机器学习/深度学习 数据可视化 PyTorch
深入解析图神经网络注意力机制:数学原理与可视化实现
本文深入解析了图神经网络(GNNs)中自注意力机制的内部运作原理,通过可视化和数学推导揭示其工作机制。文章采用“位置-转移图”概念框架,并使用NumPy实现代码示例,逐步拆解自注意力层的计算过程。文中详细展示了从节点特征矩阵、邻接矩阵到生成注意力权重的具体步骤,并通过四个类(GAL1至GAL4)模拟了整个计算流程。最终,结合实际PyTorch Geometric库中的代码,对比分析了核心逻辑,为理解GNN自注意力机制提供了清晰的学习路径。
138 7
深入解析图神经网络注意力机制:数学原理与可视化实现
|
7天前
|
机器学习/深度学习 缓存 自然语言处理
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
Tiktokenizer 是一款现代分词工具,旨在高效、智能地将文本转换为机器可处理的离散单元(token)。它不仅超越了传统的空格分割和正则表达式匹配方法,还结合了上下文感知能力,适应复杂语言结构。Tiktokenizer 的核心特性包括自适应 token 分割、高效编码能力和出色的可扩展性,使其适用于从聊天机器人到大规模文本分析等多种应用场景。通过模块化设计,Tiktokenizer 确保了代码的可重用性和维护性,并在分词精度、处理效率和灵活性方面表现出色。此外,它支持多语言处理、表情符号识别和领域特定文本处理,能够应对各种复杂的文本输入需求。
37 6
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
|
26天前
|
编解码 缓存 Prometheus
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
本期内容为「ximagine」频道《显示器测试流程》的规范及标准,我们主要使用Calman、DisplayCAL、i1Profiler等软件及CA410、Spyder X、i1Pro 2等设备,是我们目前制作内容数据的重要来源,我们深知所做的仍是比较表面的活儿,和工程师、科研人员相比有着不小的差距,测试并不复杂,但是相当繁琐,收集整理测试无不花费大量时间精力,内容不完善或者有错误的地方,希望大佬指出我们好改进!
91 16
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
|
17天前
|
Java 数据库 开发者
详细介绍SpringBoot启动流程及配置类解析原理
通过对 Spring Boot 启动流程及配置类解析原理的深入分析,我们可以看到 Spring Boot 在启动时的灵活性和可扩展性。理解这些机制不仅有助于开发者更好地使用 Spring Boot 进行应用开发,还能够在面对问题时,迅速定位和解决问题。希望本文能为您在 Spring Boot 开发过程中提供有效的指导和帮助。
63 12
|
15天前
|
开发框架 监控 JavaScript
解锁鸿蒙装饰器:应用、原理与优势全解析
ArkTS提供了多维度的状态管理机制。在UI开发框架中,与UI相关联的数据可以在组件内使用,也可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,还可以在应用全局范围内传递或跨设备传递。
33 2
|
26天前
|
Web App开发 监控 前端开发
React音频播放控制组件开发深度解析
本文介绍了构建React音频控制组件时遇到的关键问题及优化方案。主要包括: 1. **状态同步难题**:解决播放按钮与音频状态不同步的问题,通过双向绑定机制确保一致。 2. **跨浏览器兼容性**:处理Safari和Chrome预加载策略差异,确保`duration`属性正确获取。 3. **进度控制优化**:避免使用`setInterval`,采用`requestAnimationFrame`提升性能;优化拖拽交互,防止音频卡顿。 4. **音量控制进阶**:实现渐变音量调节和静音状态同步。
65 15
React-11:setState的使用
React-11:setState的使用
107 0
React-11:setState的使用
|
10月前
|
设计模式 前端开发 数据可视化
【第4期】一文了解React UI 组件库
【第4期】一文了解React UI 组件库
470 0
|
10月前
|
资源调度 前端开发 JavaScript
React 的antd-mobile 组件库,嵌套路由
React 的antd-mobile 组件库,嵌套路由
174 0

热门文章

最新文章

推荐镜像

更多