react学习记录-组件的state和setState

组件的state和setState

setState 方法由父类 Component 所提供。当我们调用这个函数的时候,React.js 会更新组件的状态 state ,并且重新调用 render 方法,然后再把 render 方法所渲染的最新的内容显示到页面上

注意,当我们要改变组件的状态的时候,不能直接用 this.state = xxx 这种方式来修改,如果这样做 React.js 就没办法知道你修改了组件的状态,它也就没有办法更新页面。在Vue中可以通过 this.state = xxx的形式去修改,但在React中要调整过来,为的是使得数据更改与页面更新渲染同步。

setState 接受对象参数

传入的对象代表了组件的新状态,但我们其实只需要传入修改的部分即可,不需要传入整个对象。如下:

constructor (props) {
    super(props)
    this.state = {
        name: 'Tomy',
        isLiked: false
    }
}

handleClickOnLikeButton () {
    this.setState({
        isLiked: !this.state.isLiked
        // 只修改isLiked
    })
}

setState 接受函数参数

调用setState的时候,React.js 并不会马上修改 state。而是把这个对象放到一个更新队列里面,稍后才会从队列当中把新的状态提取出来合并到 state 当中,然后再触发组件更新。

handleClickOnLikeButton () {
    console.log(this.state.isLiked)
    this.setState({
        isLiked: !this.state.isLiked
    })
    console.log(this.state.isLiked)
}

两次打印的都是 false,即使我们中间已经 setState 过一次了。

React.js 的 setState 把你的传进来的状态缓存起来,稍后才会帮你更新到 state 上,所以你获取到的还是原来的 isLiked

这就有点像异步代码了,所以在setState之后使用新的state去做运算就做不到了。于是需要接受函数参数的做法:

handleClickOnLikeButton () {
    this.setState((prevState) => {
      return { count: 0 }
    })
    this.setState((prevState) => {
      return { count: prevState.count + 1 } // 上一个 setState 的返回是 count 为 0,当前返回 1
    })
    this.setState((prevState) => {
      return { count: prevState.count + 2 } // 上一个 setState 的返回是 count 为 1,当前返回 3
    })
    // 最后的结果是 this.state.count 为 3
  }

这种做法可以做到利用上一次setState的结果进行运算,有变成了一个同步代码的过程。

关于setState的合并

上述代码虽然执行三次setState ,但实际上只会重新渲染一次。在React.js内部会把JavaScript的Event Loop中的消息队列的同一个消息中的setState 进行合并,之后再重新进行组件的渲染。这里还不需要了解太多深层的原理。在开发中我们只需要记住:使用React.js的时候,并不需要担心多次进行 setState 会带来性能问题。

课后练习


不能摸的狗(二)

class Dog extends Component {
  constructor () {
    super()
    /* TODO */
    this.state={
      isRunning:false,
      isBarking:false
    }
  }
  
  bark () {
    /* TODO */
    this.setState({ isBarking: true })
    setTimeout(() => this.setState({ isBarking: false }), 20)
  }
  
  run () {
    /* TODO */
    this.setState({ isRunning: true })
    setTimeout(() => this.setState({ isRunning: false }), 20)
  }
  
  handleClick(){
    this.bark();
    this.run();
  }
 
  render () {
    return (<div onClick={this.handleClick.bind(this)}>DOG</div>)
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值