React の非同期でデータを更新する setState() とその解決方法がわからない

一緒に創造し、成長するために一緒に働きましょう!「ナゲッツデイリー新プラン・8月アップデートチャレンジ」参加21日目、イベント詳細はこちら

1.setState()の説明

誰もが React をよく使っていると思いますが、React の setState() メソッドが非同期でデータを更新することをご存知ですか? 以下の例を使用して、 setState() がデータを非同期に更新する方法と、使用中に注意すべき点を分析します。

1.1 更新データ

setState() データを非同期的に更新する

ご存知のように、React は setState() を使用してデータを更新しますが、実際には setState() は非同期でデータを更新します. コードは次のとおりです。

// 导入ract
import React from 'react'
import ReactDOM from 'react-dom'

// App组件
class App extends React.Component {
  // 默认状态的值
  state = {
    count: 1
  }
  
  handleClick = () => {
    // 异步更新state
    this.setState({
      count: this.state.count + 1
    })
    console.log(this.state.count)// 1
    
  }
  
  render() {
    return (
      <div>
        <h1>计数器:{this.state.count}</h1>
        <button onClick={this.handleClick}>+1</button>
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'))
复制代码

上記のコードでは、デフォルト値 1 があり、クリック イベントのハンドラーを提供します。ボタンが 1 回クリックされると、そのデフォルト値に +1 してカウント 2 の値を作成しますが、これを出力するためです。 .count を this.setState() メソッドの直後に実行すると、実際に取得する値はまだ 1 です。これは、this.setState() メソッドの呼び出しが終了しても、状態がすぐに更新されないことを示しています。これは、this.setState が() データを非同期的に更新します。デモンストレーションの効果は次のとおりです。

1.gif

注: この構文を使用する場合、次の setState() は前の setState() に依存しないでください。

実際には this.setState() は複数回呼び出すことができますが、 this.setState() はデータを非同期に更新するため、最初の this.setState() が呼び出された後に 2 回目の this.setState() が呼び出され、結果は変わりません。 . コードは以下のように表示されます:

// 导入ract
import React from 'react'
import ReactDOM from 'react-dom'

// App组件
class App extends React.Component {
  state = {
    count: 1
  }

  handleClick = () => {
    // 前面的setState()
    this.setState({
      count: this.state.count + 1// 1 + 1
    })
    console.log('第一次调用完的count:', this.state.count)// 1

    // 后面的setState()
    this.setState({
      count: this.state.count + 1
    })
    console.log('第二次调用完的count:', this.state.count)// 1
  }

  render() {
    return (
      <div>
        <h1>计数器:{this.state.count}</h1>
        <button onClick={this.handleClick}>+1</button>
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'))
复制代码

効果は次のとおりです。

2.gif

setState() は複数回呼び出すことができますが、再レンダリングは 1 回だけ呼び出されます

this.setState() は 2 回呼び出されますが、render() は 1 回だけ実行されます (初期化中はカウントされず、ボタンがクリックされた後のみ)。これはパフォーマンスを向上させるためであり、状態を変更するたびにリセットする必要はありません。変更 ページをレンダリングします。コードは以下のように表示されます:

// 导入ract
import React from 'react'
import ReactDOM from 'react-dom'

// App组件
class App extends React.Component {
  state = {
    count: 1
  }

  handleClick = () => {
    // 前面的setState()
    this.setState({
      count: this.state.count + 1// 1 + 1
    })
    console.log('第一次调用完的count:', this.state.count)// 1

    // 后面的setState()
    this.setState({
      count: this.state.count + 1
    })
    console.log('第二次调用完的count:', this.state.count)// 1
  }

  render() {
    console.log('render调用')
    return (
      <div>
        <h1>计数器:{this.state.count}</h1>
        <button onClick={this.handleClick}>+1</button>
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'))
复制代码

効果は次のとおりです。

3.gif

1.2 推奨構文

後の this.setState() が最初の this.setState() の結果に基づいて操作を実行したい場合、どのように実装する必要がありますか? 以下の方法:

  • 推奨: setState((state,props) => {}) 構文を使用
  • パラメータ state: 最新の状態を示します
  • パラメータ props: 最新の props を示します
// 导入ract
import React from 'react'
import ReactDOM from 'react-dom'

// App组件
class App extends React.Component {
  state = {
    count: 1
  }

  handleClick = () => {
    // 前面的setState()
    // 更新state
    // 注意:这种方法也是异步更新数据
    this.setState((state, props) => {
      return {
        count: state.count + 1// 1 + 1
      }
    })

    // 后面的setState()
    this.setState((state, props) => {
      console.log('第二次调用:', state)
      return {
        count: state.count + 1
      }
    })
    console.log('count:', this.state.count)// 1
  }

  render() {
    console.log('render')
    return (
      <div>
        <h1>计数器:{this.state.count}</h1>
        <button onClick={this.handleClick}>+1</button>
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'))
复制代码

効果は次のとおりです。

1.gif

1.3 setState() の 2 番目のパラメーター

  • シナリオ: 状態の更新直後に何かを行う (ページの再レンダリングが終了する)
  • 構文: setSate(updater,[callback])
this.setState(
    (state, props) => {},// 参数1
    () => {console.log('这个回调函数会在状态更新后立即执行')}// 参数2
)
复制代码

実際には、setState() メソッドには 2 番目のパラメーターがあります。これはコールバック関数です。このコールバック関数は、状態の更新の直後に実行されるため、状態の更新後に何かをしたい場合は、このコールバック関数を使用できます。 . 実行、その使用法は次のとおりです。

// 导入ract
import React from 'react'
import ReactDOM from 'react-dom'

// App组件
class App extends React.Component {
  state = {
    count: 1
  }

  handleClick = () => {
    this.setState(
      // 参数1
      (state, props) => {
        return { count: state.count + 1 }
      },

      // 参数2:在状态更新后且重新渲染后,立即执行
      () => {
        console.log('状态更新完成:', this.state.count)
        console.log(document.getElementById('title').innerText)
        document.title = '更新后的count为:' + this.state.count
      }
    )
    console.log("异步执行完以后的count:"+this.state.count)// 1
  }

  render() {
    return (
      <div>
        <h1 id='title'>计数器:{this.state.count}</h1>
        <button onClick={this.handleClick}>+1</button>
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'))
复制代码

効果は次のとおりです。

2.gif

おすすめ

転載: juejin.im/post/7133127251704922126