setStateのreactを本当に理解していますか?(setStateの現象と原理の総合的な分析)

序文

私たちが最初にreactを学び始めたとき、私たちはしばしばsetStateを使用して状態を変更していました。私たちはそれを頻繁に使用するので、次のことを考える必要があります。なぜsetStateを使用するのですか? setStateは「非同期」ですか?この記事では、これら2つの問題に焦点を当てます

なぜsetStateを使用するのですか?

最初に簡単なsetStateの例を見てみましょう。
これはより基本的な例です。ボタンをクリックして、状態のmsgの値を変更します。

import React, {
    
     Component } from 'react'

export class App extends Component {
    
    
    state = {
    
    
        msg: 'hello world'
    }
    render() {
    
    
        return (
            <div>App
                <h2>{
    
    this.state.msg}</h2>
                <button onClick={
    
    this.change}>change</button>
            </div>
        )
    }
    // setState继承自Component
    change = () => {
    
    
        this.setState({
    
    msg: 'haha'})
    }
}

export default App

では、なぜsetStateを使用するのでしょうか。
状態を変更するとき、Reactが最新の状態に従ってインターフェースを再レンダリングすることを期待しているためです。直接変更の方法では、Reactは状態が変更されたことを認識しません。
Reactは、データの変更を監視するためにVue2またはVue3プロキシのObject.definePropertyと同様のメソッドを実装していません。反応状態の変更を通知するには、SetStateを使用する必要があります。
setStateはComponentから継承され、setStateを呼び出すと、renderメソッドが再実行されます。

setState'async'

この質問に答えるには、次のさまざまな状況の例を使用して答えてください。

例1:ライフサイクル関数での使用

1. componentDidMount関数でthis.setState割り当てを使用し、それとcomponentDidUpdate関数で出力します

import React, {
    
     Component } from 'react'

export class App extends Component {
    
    
    state = {
    
    
        count: 0
    }
    componentDidMount() {
    
    
        this.setState({
    
    count: 1})
        console.log(this.state.count) // 0
    }
    componentDidUpdate() {
    
    
        console.log(this.state.count) // 1
    }
    render() {
    
    
        return (
            <div></div>
        )
    }
    // setState继承自Component
    change = () => {
    
    
        this.setState({
    
    msg: 'haha'})
    }
}

export default App

結果を確認すると、componentDidUpdate関数は0を出力し、componentDidUpdate関数は1を出力します。これは、setStateがライフサイクルで非同期であることを意味します。

次の例を参照してください

例2:合成イベントでの使用

2.ボタンをクリックして変更イベントをトリガーし、イベントでthis.setStateを使用して状態のカウントの値を変更し、this.state.countを出力します。

import React, {
    
     Component } from 'react'
// 在合成事件里,setState是异步的
export class App extends Component {
    
    
    state = {
    
    
        count: 0
    }
    render() {
    
    
        return (
            <div>App
                <h2>{
    
    this.state.count}</h2>
                {
    
    /* 这个就是合成事件 */}
                <button onClick={
    
    this.change}>change</button>
            </div>
        )
    }
    // setState继承自Component
    change = () => {
    
    
        this.setState({
    
    count: 1})
        console.log(this.state.count) // 0
     
    }
}

export default App

結果を実行して表示する
ここに画像の説明を挿入
ボタンをクリックします。上のデータは1に変更されていますが、コンソールには9が表示されます。これはなぜですか?
理論的には、コードを実行するプロセスは上から下へと同期しています。非同期の結果は、合成イベントとライフサイクルでは、呼び出しシーケンスが更新前であるため、更新された値をすぐに取得できないため、いわゆる非同期現象が形成されます。ここでの非同期とは、非同期コードによって内部的に実装されることを意味するものではありません。

例3:setTimeoutで使用

3.タイマーの例を記述し、this.setStateを使用して値を変更し、出力します。

import React, {
    
     Component } from 'react'
export class App extends Component {
    
    
    state = {
    
    
        count: 0
    }
    componentDidMount() {
    
    
        setTimeout(() => {
    
    
            this.setState({
    
    count: 1})
            console.log(this.state.count) // 1
        }, 0)
    }
    render() {
    
    
        return (
            <div>App
                <h2>{
    
    this.state.count}</h2>
            </div>
        )
    }
}

export default App

結果を確認し、出力が1であることを確認します。これは、setTimeoutのsetStateが同期していることを示しています。

例4:ネイティブイベントでの使用

  1. ネイティブイベントの別の例として、ボタンをクリックするとクリックがトリガーされ、データが変更されて印刷されます。
import React, {
    
     Component } from 'react'
// 在原生事件中是同步的
export class App extends Component {
    
    
    state = {
    
    
        count: 0
    }
    componentDidMount() {
    
    
        document.querySelector('button').addEventListener(
            'click',
            (e) => {
    
    
                this.click()
            },
            false
        )
    }
    click() {
    
    
        this.setState({
    
    count: 1})
        console.log(this.state.count)  // 1
    }
    render() {
    
    
        return (
            <div>App
                <h2>{
    
    this.state.count}</h2>
                <button>按钮</button>
            </div>
        )
    }
}

export default App

最終的な実行結果は1であり、ネイティブイベントで同期していることを示します

要約:

setStateは、ライフサイクルイベントと合成イベントでは非同期であり、setTimeoutイベントとネイティブイベントでは同期です。

おすすめ

転載: blog.csdn.net/weixin_45745641/article/details/123534639