React class组件和hooks setState异步更新数据详解

一、 class组件setState详解

1.class组件setState异步更新数据详解

class Father extends React.Component{
  state = {
    num:0
  }
  addHandler = () => { 
    this.setState({
      num: 100
    })
    console.log('state中的值',this.state.num)
  }
  render() { 
    return (
      <div>
        <button onClick={this.addHandler}>新增</button>
        <p>显示的值 {this.state.num }</p>
      </div>
    )
  }
}
ReactDOM.render(
  <Father></Father>,
  document.getElementById('root')
) 

输出:

state中的值: 0 

分析:setState的更新是异步的,所以在setState之后立即获取num的值,输出的还是没有修改之前的值0。
注意:setState之后的代码中不要立即使用。

2.多次setState更新合并

React 内部将同一事件响应函数中的多个setState进行合并,减少setState的调用次数,也就能减少渲染的次数,提高性能。

class Father extends React.Component{
  state = {
   num:0
  }
  addHandler = () => { 
    <!-- 第一调用 -->
    this.setState({
      num: this.state.num+1
    })
    console.log('state中的值', this.state.num)
   c
    <!-- 第二次调用 -->
    this.setState({
      num: this.state.num + 1
    })
    console.log('state中的值', this.state.num)
  }
  render() { 
    return (
      <div>
        <button onClick={this.addHandler}>新增</button>
        <p>显示的值 {this.state.num }</p>
      </div>
    )
  }
} 

输出:

state中的值: 0 
state中的值: 0 

在同一个方法中我们调用了两次setState。

但是最后界面上显示的不是2;0+1+1=2。

而是显示的1。

也就是说虽然多次调用setState,但是最终只会执行最后的一次setState。

所以只会触发一次渲染界面。所以界面上显示的是1

由于界面只触发一次,所以render函数也只会触发一次

3.setState多次执行有效的方法

需要注意的是这种语法也是异步的。
setState((state, props) => { 
    参数state,表示最新的state
    参数props,表示最新的props
}) 
class Father extends React.Component{
  state = {
   num:0
  }
  addHandler = () => { 
    <!-- 在这个方法中我们多次调用了setState  -->
    this.setState((state, props) => { 
      // state 
      // props
      return {
        num: state.num+1
      }
    });
   console.log('state中的值', this.state.num)
    this.setState((state, props) => {
      // state 
      // props
      return {
        num: state.num + 10
      }
    });
    console.log('state中的值', this.state.num)
  }
  render() { 
    return (
      <div>
        <button onClick={this.addHandler}>新增</button>
        <p>显示的值 {this.state.num }</p>
      </div>
    )
  }
} 

输出:

state中的值: 0 
state中的值: 0 

但界面上最终显示的值为11,说明连续多次setState有效。

4.setState的第二个参数(解决state更新后无法立马使用新值的问题)

this.setState(
    (state, props) => {
        return {}
    },
    ()=>{
        console.log('界面完成重新渲染)后立刻执行某一个操作')
    }
) 
class Father extends React.Component{
  state = {
   num:0
  }
  addHandler = () => { 
    this.setState(
      (state, props) => {
        return {
          num: state.num + 1
        }
      },
      () => { 
        console.log('获取setState跟新后的值', this.state.num)
        console.log('dom节点',document.getElementById('#name') ); // 输出为null
        console.log('cont', document.title)
      }
    )
  }
  render() { 
    return (
      <div>
        <button onClick={this.addHandler}>新增</button>
        <p id='name'>显示的值 {this.state.num }</p>
      </div>
    )
  }
}
ReactDOM.render(
  <Father></Father>,
  document.getElementById('root')
) 

React class组件和hooks setState异步更新数据详解_第1张图片

注意: 第二个参数内部不可以获取页面中的dom。

5.两个setState放在setTimeout中

state = { count: 0 };
handleClick = () => {
    setTimeout(() => {
        this.setState({ count: this.state.count + 1 });
        this.setState({ count: this.state.count + 2 });
    }, 0);
};
render() {
    console.log(`render`);
    return (
        <>
            <div>当前计数:{this.state.count}</div>
            <button onClick={this.handleClick}>add</button>
        </>
    );
} 

点击按钮后,count的值最终变成了3,也就+1和+2的操作都执行了,render()也执行了2次。这是因为在 React 的合成事件和生命周期函数中直接调用setState,会交由 React 的性能优化机制管理,合并多个setState。而在原生事件、setTimeout中调用setState,是不受 React 管理的,故并不会合并多个setState,写了几次setState,就会调用几次setState。

二、hooks中setState方法详解

1. 参数为值或对象(常见)

2. 参数为函数(解决更新无法立马获取最新值的问题)

React class组件和hooks setState异步更新数据详解_第2张图片
v为更新前的count,最终count为11,return的值为新赋值。

你可能感兴趣的:(react.js,javascript,前端)