【青训营】-React · setState你需要了解的三件事

185 阅读1分钟

划重点

  1. 不要直接修改state
  2. state更新可能是异步的在React掌控内是异步(生命周期, react合成事件内),此外都是同步(宏任务,微任务,原生事件);异步的目的在于批量更新
  3. state更新可以被合并参数为function时不会合并

直接修改state会怎么样?

// 错误示范, 此代码不不会重新渲染组件
this.state.comment = 'Hello';

// 正确使⽤用
this.setState({comment: 'Hello'});

setState 异步,同步?

  1. 异步
// 当setState在合成事件中(React事件中)

class Demo extends React.Component {
  constructor(props) {
    super(props);
    this.state = { counter: 0 }
  }
  handleClick = () => {
    this.setState({ counter: this.state.counter + 1 })
    console.log(this.state.counter, 'handleClick') // 0
  }
  render() {
    console.log(this.state.counter, 'render') // 1
    return (<>
      <p>{this.state.counter}</p>
      <button onClick={this.handleClick}>add</button>
    </>);
  }
}

/** log **/
// 首次加载
0 "render"
// 点击click
0 "handleClick"
1 "render"
  1. 同步
// 如果把setState放置在宏任务中

setTimeout(() => {
  this.setState({ counter: this.state.counter + 1 })
  console.log(this.state.counter, 'handleClick') // 1
}, 0)

/** log **/
// 首次加载
0 "render"
// 点击click
1 "render"
1 "handleClick"

// setState在原生事件中的表现

componentDidMount() {
    document.documentElement.addEventListener('click', () => {
      this.setState({ counter: this.state.counter + 1 })
      console.log(this.state.counter, 'handleClick') // 1
    })
}

/** log **/
// 首次加载
0 "render"
// 点击click
1 "render"
1 "handleClick"

tips: 该规律同样使用与useState, 感兴趣的小伙伴可以一试

state的更新合并

  handleClick = () => {
    this.setState({ counter: this.state.counter + 1 })
    console.log(this.state.counter, 'handleClick') // 0
    this.setState({ counter: this.state.counter + 1 })
    console.log(this.state.counter, 'handleClick') // 0
    this.setState({ counter: this.state.counter + 1 })
    console.log(this.state.counter, 'handleClick') // 0
  }
  
/** log **/
// 首次加载
0 "render"
// 点击click
0 "handleClick"
0 "handleClick"
0 "handleClick"
1 "render"
  handleClick = () => {
    this.setState((state) => ({ state, counter: state.counter + 1 }))
    console.log(this.state.counter, 'handleClick') // 0
    this.setState((state) => ({ state, counter: state.counter + 1 }))
    console.log(this.state.counter, 'handleClick') // 0
    this.setState((state) => ({ state, counter: state.counter + 1 }))
    console.log(this.state.counter, 'handleClick') // 0
  }
  
/** log **/
// 首次加载
0 "render"
// 点击click
0 "handleClick"
0 "handleClick"
0 "handleClick"
3 "render"