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

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 在刚开始学习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和原生事件中是同步的

相关文章
|
7天前
|
存储 缓存 算法
HashMap深度解析:从原理到实战
HashMap,作为Java集合框架中的一个核心组件,以其高效的键值对存储和检索机制,在软件开发中扮演着举足轻重的角色。作为一名资深的AI工程师,深入理解HashMap的原理、历史、业务场景以及实战应用,对于提升数据处理和算法实现的效率至关重要。本文将通过手绘结构图、流程图,结合Java代码示例,全方位解析HashMap,帮助读者从理论到实践全面掌握这一关键技术。
43 13
|
12天前
|
前端开发 JavaScript
React 步骤条组件 Stepper 深入解析与常见问题
步骤条组件是构建多步骤表单或流程时的有力工具,帮助用户了解进度并导航。本文介绍了在React中实现简单步骤条的方法,包括基本结构、状态管理、样式处理及常见问题解决策略,如状态管理库的使用、自定义Hook的提取和CSS Modules的应用,以确保组件的健壮性和可维护性。
52 17
|
25天前
|
运维 持续交付 云计算
深入解析云计算中的微服务架构:原理、优势与实践
深入解析云计算中的微服务架构:原理、优势与实践
56 1
|
2月前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
54 3
|
2月前
|
前端开发 JavaScript
React Hooks 全面解析
【10月更文挑战第11天】React Hooks 是 React 16.8 引入的新特性,允许在函数组件中使用状态和其他 React 特性,简化了状态管理和生命周期管理。本文从基础概念入手,详细介绍了 `useState` 和 `useEffect` 的用法,探讨了常见问题和易错点,并提供了代码示例。通过学习本文,你将更好地理解和使用 Hooks,提升开发效率。
80 4
|
2月前
|
前端开发
深入解析React Hooks:构建高效且可维护的前端应用
本文将带你走进React Hooks的世界,探索这一革新特性如何改变我们构建React组件的方式。通过分析Hooks的核心概念、使用方法和最佳实践,文章旨在帮助你充分利用Hooks来提高开发效率,编写更简洁、更可维护的前端代码。我们将通过实际代码示例,深入了解useState、useEffect等常用Hooks的内部工作原理,并探讨如何自定义Hooks以复用逻辑。
|
1天前
|
网络协议 安全 网络安全
探索网络模型与协议:从OSI到HTTPs的原理解析
OSI七层网络模型和TCP/IP四层模型是理解和设计计算机网络的框架。OSI模型包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,而TCP/IP模型则简化为链路层、网络层、传输层和 HTTPS协议基于HTTP并通过TLS/SSL加密数据,确保安全传输。其连接过程涉及TCP三次握手、SSL证书验证、对称密钥交换等步骤,以保障通信的安全性和完整性。数字信封技术使用非对称加密和数字证书确保数据的机密性和身份认证。 浏览器通过Https访问网站的过程包括输入网址、DNS解析、建立TCP连接、发送HTTPS请求、接收响应、验证证书和解析网页内容等步骤,确保用户与服务器之间的安全通信。
12 1
|
18天前
|
前端开发 UED
React 文本区域组件 Textarea:深入解析与优化
本文介绍了 React 中 Textarea 组件的基础用法、常见问题及优化方法,包括状态绑定、初始值设置、样式自定义、性能优化和跨浏览器兼容性处理,并提供了代码案例。
46 8
|
1月前
|
运维 持续交付 虚拟化
深入解析Docker容器化技术的核心原理
深入解析Docker容器化技术的核心原理
46 1
|
26天前
|
存储 供应链 算法
深入解析区块链技术的核心原理与应用前景
深入解析区块链技术的核心原理与应用前景
51 0

推荐镜像

更多