有关React中使用setState的注意事项
详细信息请看官方文档
1 setState的使用方式
1.不要直接修改 State,应该使用setState
//此代码不会重新渲染组件
this.state.count = 1;2.使用方式
(1)setState(updater, [callback])
updater为返回stateChange对象的函数: (state, props) => stateChange
接收的state和props被保证为最新的(2)setState(stateChange, [callback])
stateChange为对象,
callback是可选的回调函数, 在状态更新且界面更新后才执行(3)如何得到异步更新后的状态数据?
在setState()的callback回调函数中(4)如何选择setState的方式呢?
对象方式是函数方式的简写方式
如果新状态不依赖于原状态 ===> 可以使用对象方式
如果新状态依赖于原状态 ===> 使用函数方式小案例如下:
import React, { Component } from 'react';
class Count extends Component {
    state = {
        count: 0
    }
    add1 = () => {
        //点击按钮count+1
        this.setState((state) => {
            return {
                count:state.count+1
            }
        })
        console.log('add1 setState之后',this.state.count)
    }
    add2 = () => {
        //点击按钮count+2
        const count = this.state.count+2
        this.setState({
            count
        })
        console.log('add2 setState之后',this.state.count)
    }
    add3 = () => {
        //点击按钮count+3
        this.setState(state=>({count:state.count+3}),()=>{  //在状态更新且界面更新之后回调
            console.log('add3 setState之后 callback',this.state.count)
        })
    }
    render() {
        const {count} = this.state
        console.log('render:',count)
        return (
            <div>
                <h1>Count组件当前count值:{count}</h1>
                <button onClick={this.add1}>点击+1</button>
                <button onClick={this.add2}>点击+2</button>
                <button onClick={this.add3}>点击+3</button>
            </div>
        );
    }
}
export default Count;
2 State 的更新可能是异步的
根据执行setState()的位置进行判断
如果在react控制的回调函数中: 生命周期函数、react事件监听回调,执行时异步的。
如果在非react控制的异步回调函数中: 如定时器回调、原生事件监听回调、promise.then(),执行是同步的。
小案例如下:
import React, { Component } from 'react';
class Count extends Component {
    state = {
        count: 0
    }
    countRef = React.createRef()
    add1 = () => {
        console.log('add1 setState之前',this.state.count)
        this.setState((state) => {
            return {
                count:state.count+1
            }
        })
        console.log('add1 setState之后',this.state.count)
    }
    add2 = () => {
        /**定时器中更新 */
        setTimeout(()=>{
            console.log('setTimeout setState之前',this.state.count)
            this.setState((state) => {
                return {
                    count:state.count+1
                }
            })
            console.log('setTimeout setState之后',this.state.count)
        })
    }
    add3 = () => {
        //原生DOM事件监听
        const h1node = this.countRef.current
        h1node.onclick = ()=>{
            console.log('onclick setState之前',this.state.count)
            this.setState((state) => {
                return {
                    count:state.count+1
                }
            })
            console.log('onclick setState之后',this.state.count)
        }
    }
    add4 = () => {
        //promise
        Promise.resolve().then(value=>{
            console.log('Promise setState之前',this.state.count)
            this.setState((state) => {
                return {
                    count:state.count+1
                }
            })
            console.log('Promise setState之后',this.state.count)
        })
    }
    add5 = () => {
        //setState更新使用函数形式
        console.log('函数形式 setState之前',this.state.count)
        this.setState((state) => {
            return {
                count:state.count+1
            }
        })
        console.log('函数形式 setState之后',this.state.count)
        console.log('函数形式 setState之前2',this.state.count)
        this.setState((state) => {
            return {
                count:state.count+1
            }
        })
        console.log('函数形式 setState之后2',this.state.count)
    }
    add6 = () => {
        //setState更新使用对象形式
        console.log('对象形式 setState之前',this.state.count)
        this.setState({count:this.state.count+1})
        console.log('对象形式 setState之后',this.state.count)
        console.log('对象形式 setState之前2',this.state.count)
        this.setState({count:this.state.count+1})
        console.log('对象形式 setState之后2',this.state.count)
    }
    add7 = () => {
        //setState更新使用函数与对象形式
        console.log('对象形式 setState之前',this.state.count)
        this.setState({count:this.state.count+1})
        console.log('对象形式 setState之后',this.state.count)
        console.log('函数形式 setState之前',this.state.count)
        this.setState((state) => {
            return {
                count:state.count+1
            }
        })
        console.log('函数形式 setState之后',this.state.count)
    }
    componentDidMount(){
        /**生命周期中更新 */
        console.log('componentDidMount setState之前',this.state.count)
        this.setState((state) => {
            return {
                count:state.count+1
            }
        })
        console.log('componentDidMount setState之后',this.state.count)
    }
    render() {
        const {count} = this.state
        console.log('render:',count)
        return (
            <div>
                <h1 ref={this.countRef}>Count组件当前count值:{count}</h1>
                <button onClick={this.add1}>点击+1</button>
                <button onClick={this.add2}>定时器+1</button>
                <button onClick={this.add3}>原生onclick+1</button>
                <button onClick={this.add4}>promise+1</button>
                <button onClick={this.add5}>函数形式+1</button>
                <button onClick={this.add6}>对象形式+1</button>
                <button onClick={this.add7}>函数与对象形式+1</button>
            </div>
        );
    }
}
export default Count;

3 State 的更新会被合并
关于异步的setState(),多次调用, 如何处理?
setState({}): (对象形式)合并更新一次状态, 只调用一次render()更新界面 —状态更新和界面更新都合并了
setState(fn): (函数形式)更新多次状态, 但只调用一次render()更新界面  —状态更新没有合并, 界面更新合并了。


- 本文作者: étoile
- 版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!
 
		