React - setState 的用法

一、setState 的注意点

React 中的 setState 有三个注意点

  1. setState 并不会立即更新
  2. setState 会引发组件的重新绘制
  3. 多个 setState 会合并执行

这三个点也可以合在一起来说,首先,我们应该意识到,我们想要更新 state 的值,除了state本身的数值要改变,另外render也必须要执行,这才能让state的更新有意义。

setState与生命周期函数

setState的更新会引起生命周期发生变化。这4个函数依次被调用。

  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate

在 render函数被调用的时候,this.state才得到更新,即使 shouldComponentUpdate 返回了 false,state 也依旧会更新。

正是因为state会引起生命周期的变化,所以为了优化性能,React会把更新的 state 的操作 排成一个队列,一次性将对列中的state属性更新。

获取更新后的state的值

如果想获取更新后的state的值,可以使用setState的第二个参数,这个参数接收的是一个回调函数,这个回调函数会在界面渲染之后调用。

this.setState({ 
	name: 'newName' 
}, this.changeName);

changeName = () => {
  const { name } = this.state;
  console.log(name); // 'newName' 
}

二、 setState的两种使用形式

对象形式的setState

this.setState({ 
	name: 'newName' 
});

函数形式的setState

// 第一种
this.setState((preState, props) => {
    return {name: props.name}
});

// 第二种
this.setState((preState, props) => ({
    name: preState.name
}));

三、setState 的更新状态

判断setState()更新状态时异步还是同步的,主要是看执行setState的位置

  1. 在React控制的回调函数中(生命周期钩子,react事件监听回调)这种情况是异步的。
  2. 在非react控制的异步回调函数中(定时器回调/原生事件监听回调/promise回调)这种情况是同步的。

异步

handleClick = () => {
    this.setState({
      num: 1
    }, this.showNum)
    console.log(this.state.num); // 0
  }
 
 showNum = () => {
    console.log(this.state.num); // 1
 }

同步

handleClick = () => {
  setTimeout(() => {
    console.log('setTimeout 更新之前:', this.state.num); // 0
    this.setState(state => ({ num: state.num + 1 }))
    console.log('setTimeout 更新之后:', this.state.num); // 1
  })
}

四、setState多次调用的问题

两个函数式setState的情况(不会合并)

changeNum = () => {
  console.log(this.state.count);
  this.setState(state => ({ num: state.num + 1 }))
  this.setState(state => ({ num: state.num + 1 }))
}
changeNum(); // 0
changeNum(); // 2

两个对象式setState的情况(会合并)

  changeNum = () => {
    console.log("222", this.state.num);
    this.setState({num: this.state.num + 1})
    this.setState({num: this.state.num + 1})
  }
changeNum(); // 0
changeNum(); // 1

先函数式后对象式(会合并)

  changeNum = () => {
    console.log("222", this.state.num);
    this.setState(state => ({ num: state.num + 1 }))
    this.setState({num: this.state.num + 1})
  }
changeNum(); // 0
changeNum(); // 1

先对象式后函数式(不会合并)

  changeNum = () => {
    console.log("222", this.state.num);
    this.setState({num: this.state.num + 1})
    this.setState(state => ({ num: state.num + 1 }))
  }
changeNum(); // 0
changeNum(); // 2

总结

函数式传入的state总是能够获取到最新的state,但是对象式则不能,但是最后render只会更新一次。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值