001_探究setState的用法

本文深入探讨React组件中setState方法的使用,包括基本使用、异步调用、同步调用以及连续调用的情况。通过示例代码解析setState在不同场景下的行为,展示了如何根据需求选择合适的调用方式,以及在并发更新时如何合并state更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、setState的基本使用

import React, { Component } from 'react'

export default class index extends Component {
    state = { count: 0 }

    /**
     * 如果不依赖原来的值,建议使用对象方式调用setState
     */
    incrementByObject = () => {
        this.setState({ count: 5 }, () => {
            /**
            * 这个方法没有参数,但是可以在这里获取更新之后state的值。
            * callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
            */
            console.log('incrementByObject', this.state.count)
        })
    }

    /**
     *  如果依赖原来的值,建议使用方法方式调用setState
     */
    incrementByFunction = () => {
        this.setState(state => {
            return { count: state.count + 1 }
        }, () => {
            /**
            * 这个方法没有参数,但是可以在这里获取更新之后state的值。
            * callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
            */
            console.log('incrementByFunction', this.state.count)
        })
    }

    render() {
        const { count } = this.state
        console.log('render', count)
        return (
            <div>
                <h2>当前值是:{this.state.count}</h2>
                <button onClick={this.incrementByObject}>点击我+1==ByObject</button>
                <button onClick={this.incrementByFunction}>点击我+1==ByFunction</button>
            </div>
        )
    }
}

二、setState异步调用的方式

import React, { Component } from 'react'

export default class index extends Component {
    state = { count: 0 }

    /**
     * 1.如果不依赖原来的值,建议使用对象方式调用setState
     * 2.console.log('incrementByObject之前', this.state.count)
     *   和console.log('incrementByObject之后', this.state.count)
     *   两句代码是在render方法和this.setState方法回调之前执行。不是
     *   顺序执行的。所以是异步
     */
    incrementByObject = () => {
        console.log('incrementByObject之前', this.state.count)
        this.setState({ count: 5 }, () => {
            /**
            * 这个方法没有参数,但是可以在这里获取更新之后state的值。
            * callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
            */
            console.log('incrementByObject', this.state.count)
        })
        console.log('incrementByObject之后', this.state.count)
    }

    /**
     *  1.如果依赖原来的值,建议使用方法方式调用setState
     *  2.console.log('incrementByFunction之前', this.state.count)
     *    和console.log('incrementByFunction之后', this.state.count)
     *    两句代码是在render方法和this.setState方法回调之前执行。不是
     *    顺序执行的。所以是异步
     */
    incrementByFunction = () => {
        console.log('incrementByFunction之前', this.state.count)
        this.setState(state => {
            return { count: state.count + 1 }
        }, () => {
            /**
            * 这个方法没有参数,但是可以在这里获取更新之后state的值。
            * callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
            */
            console.log('incrementByFunction', this.state.count)
        })
        console.log('incrementByFunction之后', this.state.count)
    }

    /**
     *  1.console.log('componentDidMount之前', this.state.count)
     *    和console.log('componentDidMount之后', this.state.count)
     *    两句代码是在render方法和this.setState方法回调之前执行。不是
     *    顺序执行的。所以是异步
     */
    componentDidMount() {
        console.log('componentDidMount之前', this.state.count)
        this.setState({ count: 10 }, () => {
            /**
            * 这个方法没有参数,但是可以在这里获取更新之后state的值。
            * callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
            */
            console.log('componentDidMount', this.state.count)
        })
        console.log('componentDidMount之后', this.state.count)
    }

    render() {
        const { count } = this.state
        console.log('render', count)
        return (
            <div>
                <h2>当前值是:{this.state.count}</h2>
                <button onClick={this.incrementByObject}>点击我+1==ByObject</button>
                <button onClick={this.incrementByFunction}>点击我+1==ByFunction</button>
            </div>
        )
    }
}

三、setState同步调用的方式

import React, { Component } from 'react'

/**
 * setTimeout/Promise/dom绑定事件方式阻碍了react的事务,
 * 所以影响了this.setState方法的异步调用
 */
export default class index extends Component {
    state = { count: 0 }

    /**
     * 1.如果不依赖原来的值,建议使用对象方式调用setState
     * 2.console.log('incrementByObject之前', this.state.count)
     *   和console.log('incrementByObject之后', this.state.count)
     *   两句代码是在render方法和this.setState方法回调之前执行。不是
     *   顺序执行的。所以是异步
     */
    incrementByObject = () => {
        console.log('incrementByObject之前', this.state.count)
        this.setState({ count: 5 }, () => {
            /**
            * 这个方法没有参数,但是可以在这里获取更新之后state的值。
            * callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
            */
            console.log('incrementByObject', this.state.count)
        })
        console.log('incrementByObject之后', this.state.count)
    }

    /**
     * 通过setTimeout实现this.setState方法的同步
     * 执行顺序是
     * 1.console.log('incrementByObject之前', this.state.count)
     * 2.render
     * 3.this.setState方法回调执行
     * 4.console.log('incrementByObject之后', this.state.count)
     */
    incrementByObjectAndSetTimeoutSync = () => {
        setTimeout(() => {
            this.incrementByObject()
        })
    }

    /**
     * 通过Promise实现this.setState方法的同步
     * 执行顺序是
     * 1.console.log('incrementByObject之前', this.state.count)
     * 2.render
     * 3.this.setState方法回调执行
     * 4.console.log('incrementByObject之后', this.state.count)
     */
    incrementByObjectAndPromiseSync = () => {
        Promise.resolve().then(() => {
            this.incrementByObject()
        })
    }

    /**
     * 通过dom事件实现this.setState方法的同步
     * 执行顺序是
     * 1.console.log('incrementByObject之前', this.state.count)
     * 2.render
     * 3.this.setState方法回调执行
     * 4.console.log('incrementByObject之后', this.state.count)
     */
    incrementByObjectAndClickSync = () => {
        console.log('incrementByObjectAndClickSync',this.refs.bindClick)
        this.refs.bindClick.onclick = () => {
            this.incrementByObject()
        }
    }

    /**
     *  1.如果依赖原来的值,建议使用方法方式调用setState
     *  2.console.log('incrementByFunction之前', this.state.count)
     *    和console.log('incrementByFunction之后', this.state.count)
     *    两句代码是在render方法和this.setState方法回调之前执行。不是
     *    顺序执行的。所以是异步
     */
    incrementByFunction = () => {
        console.log('incrementByFunction之前', this.state.count)
        this.setState(state => {
            return { count: state.count + 1 }
        }, () => {
            /**
            * 这个方法没有参数,但是可以在这里获取更新之后state的值。
            * callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
            */
            console.log('incrementByFunction', this.state.count)
        })
        console.log('incrementByFunction之后', this.state.count)
    }

    /**
     *  1.console.log('componentDidMount之前', this.state.count)
     *    和console.log('componentDidMount之后', this.state.count)
     *    两句代码是在render方法和this.setState方法回调之前执行。不是
     *    顺序执行的。所以是异步
     */
    componentDidMount() {
        console.log('componentDidMount之前', this.state.count)
        this.setState({ count: 10 }, () => {
            /**
            * 这个方法没有参数,但是可以在这里获取更新之后state的值。
            * callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
            */
            console.log('componentDidMount', this.state.count)
        })
        console.log('componentDidMount之后', this.state.count)
    }

    render() {
        const { count } = this.state
        console.log('render', count)
        return (
            <div>
                <h2>当前值是:{this.state.count}</h2>
                <button onClick={this.incrementByObject}>点击我+1==ByObject</button>
                <button onClick={this.incrementByFunction}>点击我+1==ByFunction</button>
                <hr />
                <button onClick={this.incrementByObjectAndSetTimeoutSync}>通过setTimeout回调实现同步</button>
                <button onClick={this.incrementByObjectAndPromiseSync}>通过Promise回调实现同步</button>
                <button onClick={this.incrementByObjectAndClickSync}>通过dom事件回调实现同步</button>
                <button ref="bindClick">setState===Sync</button>
            </div>
        )
    }
}

四、setState连续调用

import React, { Component } from 'react'

/**
 * setState连续调用的时候,会出现合并的情况
 */
export default class index extends Component {
    state = { count: 0 }

    /**
     * 调用顺序
     * 1.console.log('incrementByObject之前', this.state.count) 0
     * 2.console.log('incrementByObject之后', this.state.count) 0
     * 3.render 1
     * 4.console.log('incrementByObject1', this.state.count) 1
     * 5.console.log('incrementByObject2', this.state.count) 1
     */
    incrementByObject = () => {
        console.log('incrementByObject之前', this.state.count)
        this.setState({ count: this.state.count + 1 }, () => {
            console.log('incrementByObject1', this.state.count)
        })
        this.setState({ count: this.state.count + 1 }, () => {
            console.log('incrementByObject2', this.state.count)
        })
        console.log('incrementByObject之后', this.state.count)
    }

    /**
     * 调用顺序
     * 1.console.log('incrementByFunction之前', this.state.count) 0
     * 2.console.log('incrementByFunction之后', this.state.count) 0
     * 3.render 2
     * 4.console.log('incrementByFunction1', this.state.count) 2
     * 5.console.log('incrementByFunction2', this.state.count) 2
     */
    incrementByFunction = () => {
        console.log('incrementByFunction之前', this.state.count)
        this.setState(state => {
            return { count: state.count + 1 }
        }, () => {
            console.log('incrementByFunction1', this.state.count)
        })
        this.setState(state => {
            return { count: state.count + 1 }
        }, () => {
            console.log('incrementByFunction2', this.state.count)
        })
        console.log('incrementByFunction之后', this.state.count)
    }

    componentDidMount() {
        console.log('componentDidMount之后', this.state.count)
    }

    render() {
        const { count } = this.state
        console.log('render', count)
        return (
            <div>
                <h2>当前值是:{this.state.count}</h2>
                <button onClick={this.incrementByObject}>点击我+1==ByObject</button>
                <button onClick={this.incrementByFunction}>点击我+1==ByFunction</button>
            </div>
        )
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值