我们都知道在React中,setState() 方法是用来改变组件状态的,在项目中也一直用,也没有出现什么问题(使用方法太简单了),但今天看了一篇文章,提到了setState 使用时的两个注意点,加深了对setState()的认识。

  setState() 最简单的使用方式,就是给它传递一个对象,对象中的属性就是我们要改变的状态,对象中只写我们要改变的那些状态就可以了,react 会把我们这次所做的改变和原来没有做改变的状态进行合并,形成最新的状态,重新渲染组件。写一个简单的例子,点击按钮显示点击的次数,create-react-app 创建项目,在App.js 中写以下内容

import React from "react";

export default class App extends React.Component {

    state = {
counter: 0
}
handleClick = () => {
this.setState({
counter: this.state.counter + 1
})
}
render() {
return (
<div>
<p>点击了{this.state.counter}次</p>
<button onClick={this.handleClick}>点击</button>
</div>
)
}
}

  再简单不过了,但这时,你想增加一个是否点击的状态hasButtonBeenClicked, 只要counter > 0 就算点击了,相当然的,在setState() 方法中,加了

hasButtonBeenClicked 的更改

this.setState({
counter: this.state.counter + 1,
hasButtonBeenClicked: this.state.counter > 0 });

  app.js 更改如下:

export default class App extends React.Component {

    state = {
counter: 0,
hasButtonBeenClicked: false // 点击状态,默认是false
}
handleClick = () => {
this.setState({
counter: this.state.counter + 1,
hasButtonBeenClicked: this.state.counter > 0 // 更改点击状态
});
}
render() {
return (
<div>
<p>是否点击了{this.state.hasButtonBeenClicked.toString()}, 点击了{this.state.counter}次</p>
<button onClick={this.handleClick}>点击</button>
</div>
)
}
}

  你点击按钮一次,发现一个问题,是否点击显示false, 但确显示了点击了1次。

  

  这就是setState()的异步操作,一直知道setState()是异步改变状态,但没有这么写过,当调用setState 改变件的状态的时候,它并不会立即生效,React 为了提高效率,可能选择把几个状态的更改作为一组,一起改状态。也就是setState 中,如果我们更改的第二个或以后的状态,如果依赖第一个状态的改变,它有可能不生效。由于异步操作,第二个或以后的状态,不会取到最新的第一个状态的值。第二行中的hasButtonBeenClicked 中的this.state.counter 并不会获取到第一行中设置的最新状态,它仍然获取到的是this.state.counter 的旧值。

  如果,第二个状态依赖第一个状态,它就要用到setState 的第二个参数,回调函数,只有第一个状态set 成功之后,它才会执行这个回调, setState() 更改如下

handleClick = () => {
this.setState({ counter: this.state.counter + 1 },
() => this.setState({ hasButtonBeenClicked: this.state.counter > 0 }));
}

  第二个注意点,就是重复更改一个值。当使用seState()重复地修改一个状态的值的时候(handleClick的for循环),它并不会把所有的装态值都反应出来,而是取一个最近的值就完事了。

handleClick = () => {
for (let index = 0; index < 5; index++) {
this.setState({ counter: this.state.counter + 1 });
}
}

  当点击按钮的时候,它显示的是1, 而不是5. 每点击一次,只加1. 这时要使用setState的第二种方式,setState的第一个参数,除了对象外,还可以接受一个函数(state, prop) 作为参数,要返回更新状态, 如下,这时你会发现显示5.

handleClick = () => {
for (let index = 0; index < 5; index++) {
this.setState(state => ({
counter: state.counter + 1
}))
}
}

React 的setState 理解的更多相关文章

  1. React的setState分析

    前端框架层出不穷,不过万变不离其宗,就是从MVC过渡到MVVM.从数据映射到DOM,angular中用的是watcher对象,vue是观察者模式,react就是state了. React通过管理状态实 ...

  2. React中setState同步更新策略

    setState 同步更新 我们在上文中提及,为了提高性能React将setState设置为批次更新,即是异步操作函数,并不能以顺序控制流的方式设置某些事件,我们也不能依赖于this.state来计算 ...

  3. 初学React,setState后获取到的thisstate没变,还是初始state?

    问题:(javascript)初学React,setState后获取到的thisstate没变,还是初始state?描述: getInitialState(){ return {data:[]}; } ...

  4. React中setState学习总结

    react中setState方法到底是异步还是同步,其实这个是分在什么条件下是异步或者同步. 1.先来回顾一下react组件中改变state的几种方式: import React, { Compone ...

  5. React的setState学习及应用

    React的setState学习及应用 一:作用: setState() 将对组件 state 的更改排入队列,并通知 React 需要使用更新后的 state 重新渲染此组件及其子组件.这是用于更新 ...

  6. 「React Native笔记」在React的 setState 中操作数组和对象的多种方法(合集)

    运用在React 中 setState的对象.数组的操作时是不能用类似array.push()等方法,因为push没有返回值,setState后会出现state变成Number,为了方便他人和自己查看 ...

  7. React中setState 什么时候是同步的,什么时候是异步的?

    class Example extends React.Component { constructor() { super(); this.state = { val: 0 }; } componen ...

  8. react面试题——理解setState(源码object.assign)

    setState是异步的方式 this.setState({     counter:this.state.counter+1 }) console.log(this.state.counter) s ...

  9. React之setState()

    我们知道,在react中更新单个组件下state中的数据可以用setState()函数来实现,并且可以通过两种传参方式:对象.函数. 另外从文档中我们也可以了解到react可以将多个setState( ...

随机推荐

  1. Git创建与简单使用

    一. 服务器端 创建空的仓库(以项目tm201为例) 1. git账户登录 2. 新建仓库目录 mkdir tm101.git && cd tm201.git 3. git初始化新的空 ...

  2. Linux中的帮助文件

  3. C++中typedef和define的区别

    typedef和#define的用法与区别 一.typedef的用法 在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分,但它并不实际分配内存空间,实例像: ...

  4. 【pytorch】torch.utils.data.DataLoader

    简介 DataLoader是PyTorch中的一种数据类型.用于训练/验证/测试时的数据按批读取. torch.utils.data.DataLoader(dataset, batch_size=1, ...

  5. 【DP】【P5615】 [MtOI2019] 时间跳跃

    Description 给定 \(n\) 条边,第 \(i\) 条边的长度为 \(i\),每条边都有 \(50\%\) 的概率被选择,求如果选出的边能组成一个平面凸多边形,则方案的权值是方案中边的数量 ...

  6. awesome-RecSys

    https://github.com/jihoo-kim/awesome-RecSys?fbclid=IwAR1m6OebmqO9mfLV1ta4OTihQc9Phw8WNS4zdr5IeT1X1OL ...

  7. Eclipse启动发生的错误:An internal error occurred during: "Initializing Java Tooling".

    1.启动Eclipse时,初始化异常:An internal error occurred during: "Initializing Java Tooling". 解决方案:wi ...

  8. Linux stty命令

    stty是linux下改变和打印终端设置的常用命令. 一.参数: 1.打印终端行设置 -a,--all   以人可读的方式打印所有当前设置:-a参数比单独的stty命令输出的终端信息更详细 -g,-- ...

  9. 疯了!同事又问我为什么不能用 isXXX

    最近在做Code Review,写下了这篇文章:代码写成这样,老夫无可奈何!,说多了都是泪啊.. 最近又有人同事跑过来质疑我: 为什么变量名取名不能用 isXXX 这种方式,这样有什么问题?! 醉了, ...

  10. Java小学四则运算

    本次作业要求来自:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2166 github远程仓库的地址:https://github.c ...