setState()是react为我提供的状态管理工具

比如现在有下面的这样一段代码:

class MyComponent extends React.Component {

constructor(props) {

super(props);
this.state = {count: this.state.count + 1
};
复制代码

} }

我们如果想要对这个 state 进行更新的话,就可以这样使用 setState():

this.setState({

count: 1

});

你可能不知道的 最基本的用法世人皆知,但是,在 React 的文档下面,还写着,处理关于异步更新 state 的问题的时候,就不能简单地传入对象来进行更新了。这个时候,需要采用另外一种方式来对 state 进行更新。

setState() 不仅能够接受一个对象作为参数,还能够接受一个函数作为参数。函数的参数即为 state 的前一个状态以及 props。

所以,我们可以向下面这样来更新 state:

this.setState((prevState, props) => ({ count: prevState.count + 1 }));

这样写的话,能够达到同样的效果。那么,他们之间有什么区别呢?

区别 我们来详细探讨一下为什么会有两种设置 state 的方案,他们之间有什么区别,我们应该在何时使用何种方案来更新我们的 state 才是最好的。

此处,为了能够明确的看出 state 的更新,我们采用一个比较简单的例子来进行说明。

我们设置一个累加器,在 state 上设置一个 count 属性,同时,为其增加一个 increment 方法,通过这个 increment 方法来更新 count。

此处,我们采用给 setState() 传入对象的方式来更新 state,同时,我们在此处设置每调用一次 increment 方法的时候,就调用两次 setState()。

具体的代码如下:

class IncrementByObject extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; this.increment = this.increment.bind(this); }

// 此处设置调用两次 setState() increment() { this.setState({ count: this.state.count + 1 });

this.setState({count: this.state.count + 1
});
复制代码

}

render() {

return (<div><button onClick={this.increment}>IncrementByObject</button><span>{this.state.count}</span></div>
);
复制代码

} }

ReactDOM.render(

, document.getElementById('root') );

这时候,我们点击 button 的时候,count 就会更新了。但是,可能与我们所预期的有所差别。我们设置了点击一次就调用两次 setState(),但是,count 每一次却还是只增加了 1,所以这是为什么呢?

其实,在 React 内部,对于这种情况,采用的是对象合并的操作,就和我们所熟知的 Object.assign() 执行的结果一样。

比如,我们有以下的代码:

Object.assign({}, { a: 2, b: 3 }, { a: 1, c: 4 }); 那么,我们最终得到的结果将会是 { a: 1, b: 3, c: 4 }。对象合并的操作,属性值将会以最后设置的属性的值为准,如果发现之前存在相同的属性,那么,这个属性将会被后设置的属性所替换。所以,也就不难理解为什么我们调用了两次 setState() 之后,count 依然只增加了 1 了。

用简短的代码说明就是这样:

this.setState({ count: this.state.count + 1 });

// 同理于 Object.assign({}, this.state, { count: this.state.count + 1 }); 以上是我们采用对象的方式传入 setState() 来更新 state 的说明。接下来我们再看看使用函数的方式来更新 state 会有怎么样的效果呢?

我们将上面的累加器采用另外的方式来实现一次,在 setState() 的时候,我们采用传入一个函数的方式来更新我们的 state。

class IncrementByFunction extends React.Component {

constructor(props) {

super(props);
this.state = {count: 0
};this.increment = this.increment.bind(this);
复制代码

}

increment() {

// 采用传入函数的方式来更新 state
this.setState((prevState, props) => ({count: prevState.count + 1
}));
this.setState((prevState, props) => ({count: prevState.count + 1
}));
复制代码

}

render() {

return (<div><button onClick={this.increment}>IncrementByFunction</button><span>{this.state.count}</span></div>
);
复制代码

} }

ReactDOM.render( , document.getElementById('root') );

当我们再次点击按钮的时候,就会发现,我们的累加器就会每次增加 2 了。

我们可以通过查看 React 的源代码来找出这两种更新 state 的区别 (此处只展示通过传入函数进行更新的方式的部分源码)。

在 React 的源代码中,我们可以看到这样一句代码:

this.updater.enqueueSetState(this, partialState, callback, 'setState'); 然后,enqueueSetState 函数中又会有这样的实现:

queue.push(partialState); enqueueUpdate(internalInstance); 所以,与传入对象更新 state 的方式不同,我们传入函数来更新 state 的时候,React 会把我们更新 state 的函数加入到一个队列里面,然后,按照函数的顺序依次调用。同时,为每个函数传入 state 的前一个状态,这样,就能更合理的来更新我们的 state 了。

问题所在 那么,这就是传入对象来更新 state 会导致的问题吗?当然,这只是问题之一,还不是主要的问题。

我们之前也说过,我们在处理异步更新的时候,需要用到传入函数的方式来更新我们的 state。这样,在更新下一个 state 的时候,我们能够正确的获取到之前的 state,并在在其基础之上进行相应的修改。而不是简单地执行所谓的对象合并。

所以说,我们建议,在使用 setState 的时候,采用传入函数来更新 state 的方式,这样也是一个更合理的方式。

转载于:https://juejin.im/post/5c7cd4b8e51d457cde559cea

react 之 setState相关推荐

  1. react使用setState注意事项

    React设计setState方法就是为了重新渲染页面 看看下面的代码实现的结果: state = {value : 0 }function test() {this.setState({ value ...

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

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

  3. [react] react中setState的第二个参数作用是什么呢?

    [react] react中setState的第二个参数作用是什么呢? 第二个参数是一个callback函数,用于setState设置state的属性值成功之后的回调,此时调用this.state.p ...

  4. React之setState使用

    <!DOCTYPE html> <html> <head> <meat charset="UTF-8"> <title> ...

  5. react 解决 setState 异步问题

    react 解决 setState 异步问题 参考文章: (1)react 解决 setState 异步问题 (2)https://www.cnblogs.com/crazycode2/p/97158 ...

  6. React学习笔记六 React拓展 - SetState

    React拓展 - setState setState更新状态的两种写法 1.setState({}, [callback]) export default class Test extends Co ...

  7. React中setState方法详解

    一.为什么要使用 setState 方法,如何用? 在 React 中,组件分为 有状态组件 和 无状态组件,有状态组件就是能够定义 state 的组件,比如类组件,无状态组件反之,比如函数组件.st ...

  8. React 项目----setState 方法修改 state (16)

    在class 类中,构造器里面有一个实例变量state ,这个也是class 组件和function组件之间的区别.class 组件有自己的私有的数据 export default class Bin ...

  9. 关于react中setState的深入理解

    在react中,通常通过state或props,来控制整个组件的状态.一旦state或props发生改变,整个组件会被重新渲染.在setState的理解上,可能会存在一些误区. setState的基本 ...

最新文章

  1. 记一次单机系统的性能优化:最后竟是 TCP 的锅
  2. Python-数据结构-哈希表
  3. Linux下使用NTFS格式移动硬盘
  4. CSS 3 中的伪类选择器
  5. python调用arcgis_arcgis python 调用工具两种两种方法
  6. 为什么有的人喜欢夜间工作_为什么开发人员喜欢在夜间编码
  7. 四旋翼双环PID控制
  8. win8+sdk8+vs2012+freeglut+glew开发opengl
  9. php array函数 array_chunk把数组分割成相同的数组大小
  10. The VMRC console has disconnected solution
  11. Windows下设置Mongodb用户名密码
  12. 计算机中什么是数组公式,数组公式指南和示例
  13. Android Studio 快捷用法
  14. CSS实现炫酷动画背景
  15. WPS:WPS的论文使用技巧之如何对不同章节设置不同的页眉(图文教程)
  16. 嵌入式入门学习笔记1:资料收集
  17. Django教程:第一个Django应用程序(1部分)
  18. DHS:Blueprint for a Secure Cyber Future
  19. iOS开发中多线程的那些事
  20. 推箱子小游戏自制100关,有兴趣可以试一试。(头文件和源文件分开)游戏截图已发。

热门文章

  1. 自制ACL+DHCP实验(初版)
  2. 方格分割 蓝桥杯心得
  3. vs code 列编辑模式
  4. PHP脚本管理kvm,kvm管理脚本
  5. android ndk怎样加载o文件_JNI初探之NDK 开发环境配置
  6. 70个Python练手项目列表 预祝大家 快乐
  7. 非计算机专业的人要如何学python?
  8. 网络工程师,不需要学Linux?
  9. 练习7-11 字符串逆序 (15 分)
  10. 后端 消息 转发_小程序转发探索示例