02-setState

不可变值

不能直接修改 state的值,必须通过this.setState修改状态值

import React, { Component } from 'react';
import ReactDOM from 'react-dom'
class App extends Component {
  constructor(props) {
    super(props);
    this.state = { 
      list: [1,2,3,4],
      obj: {name1:'张三',name2: '李四'}
     }
  }
  handleClick = () =>{
    const listCopy = this.state.list.slice();
    listCopy.push(100);
    this.setState({
      // list: [...this.state.list,100], //追加
      // list: this.state.list.concat(100) //追加
      // list: this.state.list.slice(1) //截取
      // list: listCopy //生成副本 对副本怎么操作都不会影响原状态数组
    })
  }
  handleClick2 = () =>{
    this.setState({
      // obj: {...this.state.obj,...{name3: '王五'}} 
      obj : Object.assign(this.state.obj, {name3: '王五'})
    })
  }
  render() { 

    return ( <div>
      {this.state.list.join(' ')} <br/>
 
      <button onClick={this.handleClick}> 修改数组</button>
      <button onClick={this.handleClick2}> 修改对象</button>
    </div> );
  }
}
 
export default App;
ReactDOM.render(<App />,document.getElementById('root'));

注意不可以使用 push pop splice 修改状态 因为会改变原数组。违反不可变值
当状态是对象或者数组时,修改状态不可以改变原对象或者数组的值。可以使用结构赋值等方法,返回一个全新的数组或者对象进行更新状态操作

this.setState方法是同步更新还是异步更新

在react控制的事件中或者在react生命周期中使用this.setState 是异步的
在元素dom事件 或者setTimeout是同步的

this.state = { 
      count: 0
     }
 render() { 
   componentDidMount () {
    this.setState({count:this.state.count+1});
    console.log(this.state.count); //  这里是异步更新
    
    const button = document.getElementById('button');//绑定原生的事件方法 不受react控制 修改状态是同步的
    button.addEventListener('click',()=>{
      this.setState({count:this.state.count+1});
      console.log(this.state.count); //  这里是同步更新
    })
  }
  handleClick3 = () =>{
    this.setState({count:this.state.count+1});
    console.log(this.state.count); // 这里是异步的
  }
 //定时器内修改 同步
  setTimeClick = () =>{
    setTimeout(() => {
      this.setState({count:this.state.count+1});
    console.log(this.state.count); //  这里是同步的
    }, 0);
  }
  return ( <div>
  {this.state.count}
     <button onClick={this.handleClick3}> + react事件 异步</button>
     <button id='button'>+ js原生事件 同步</button>
     <button onClick={this.setTimeClick}>定时器 + 同步</button>
   </div> );
 }

修改状态可能会被合并

  constructor(props) {
    super(props);
    this.state = { 
      count2:0
     }
  }
  hebing = () =>{
    this.setState({count2:this.state.count2+1}) //状态会被合并
    this.setState({count2:this.state.count2+1})
    this.setState({count2:this.state.count2+1})
  }
  render() { 

    return ( <div>
      <h1>count2: {this.state.count2}</h1>
      <button id='button'>+ js原生事件 同步</button>
    </div> );
  }

在上面的例子中状态只会被加一次 结果为1

  hebing = () =>{
	this.setState((state)=>({
      count2: state.count2+1
    }))
    this.setState((state)=>({
      count2: state.count2+1
    }))
    this.setState((state)=>({
      count2: state.count2+1
    }))
  }

运用函数的方式修改可以避免状态更新异常 结果为3

  hebing = () =>{
    // this.setState({count2:this.state.count2+1})
    // this.setState({count2:this.state.count2+1})
    // this.setState({count2:this.state.count2+1})
    this.setState((state)=>({
      count2: state.count2+1
    }))
    this.setState({count2:this.state.count2+1})
    this.setState((state)=>({
      count2: state.count2+1
    }))
  }

注意不要对象和函数混用 第一次执行setState,count为1,第二次执行,this.state仍然是没有更新的状态,所以this.state.count又打回了原形为0,加1以后变成1,最后再执行setState,所以最终count的结果是2。(render依然只执行一次)

setState的第二个回调参数会在更新state,重新触发render后执行。

修改状态对象和函数如何选择

修改状态时,当要依赖原状态的时候建议使用函数方式进行修改。当修改的状态与原状态没有关系的时候建议使用对象方式。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值