001_探究setState的用法

一、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>
        )
    }
}
__setstate__和__getstate__是Python中的两个特殊方法,用于序列化和反序列化对象。当我们需要将一个对象保存到文件或者通过网络传输时,我们需要将其序列化为字节流,然后再反序列化为对象。而__setstate__和__getstate__就是用来实现这个功能的。 __getstate__方法返回一个字典,其中包含了需要序列化的对象的状态信息。这个字典会被pickle模块序列化为字节流。而__setstate__方法则接受一个字典作为参数,用于恢复对象的状态信息。 下面是一个简单的例子,演示了如何使用__getstate__和__setstate__方法来序列化和反序列化一个对象: ```python import pickle class MyClass: def __init__(self, name): self.name = name def __getstate__(self): return {'name': self.name} def __setstate__(self, state): self.name = state['name'] obj = MyClass('test') data = pickle.dumps(obj) new_obj = pickle.loads(data) print(new_obj.name) # 输出:test ``` 在这个例子中,我们定义了一个名为MyClass的类,其中包含了一个属性name。我们实现了__getstate__和__setstate__方法,用于序列化和反序列化对象。在__getstate__方法中,我们返回了一个字典,其中包含了需要序列化的对象的状态信息。在__setstate__方法中,我们接受一个字典作为参数,用于恢复对象的状态信息。 我们创建了一个MyClass的实例,并将其序列化为字节流。然后我们使用pickle.loads方法将字节流反序列化为一个新的对象。最后,我们输出了新对象的name属性,验证了反序列化的正确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值