react(含hooks)中同步获取state值的一些方法

环境

"dependencies": {
    "babel-plugin-transform-decorators-legacy": "^1.3.5",
    "customize-cra": "^1.0.0",
    "rc-form": "^2.4.11",
    "react": "^17.0.1",
    "react-app-rewired": "^2.1.8",
    "react-dom": "^17.0.1",
    "react-router-dom": "^5.2.0",
    "react-scripts": "^4.0.1",
    "redux": "^4.0.5"
  },

代码示例:

hooks

import {useState} from "react";

export default function Pre04SetStateSync() {
    const [counter, setCounter] = useState(0)
    const add = () => {
        setCounter(counter + 1)
        console.log({counter})
    }
    return <>
        

同步SetState

请观察控制台

}

class

export default class Pre04SetStateSync extends React.Component{
    state = {
        counter:0
    }
    add = () => {
        this.setState({counter:this.state.counter + 1})
        console.log('~~this.state.counter',this.state.counter)
    }

    render() {
        return <>
            

同步SetState

请观察控制台

} }

hooks结构中的setCounter(xxx)相当于class组件写法中setState({counter: xxx})

可以对比控制台看到,这样直接setCounter(setState)后立即输出的counter的是上一次的值,而按钮上显示正确,说明本次更新是异步的(react这样设计是为了批量更新而提高性能),打印时counter还没来得及改变。如果需要set完后立即取到counter的最新值,可以按如下方法实现同步的效果。

异步写成同步的方法

1. 写在setTimeout中

注意,只适用于class组件

add = () => {
    setTimeout(()=>{
        this.setState({counter:this.state.counter + 1})
        console.log('~~this.state.counter',this.state.counter)
    },0)
}

2. 合成事件使用原生事件替代

注意,只适用于class组件

// 原生事件
export default class Pre04SetStateSync extends React.Component {
    state = {
        counter: 0
    }

    componentDidMount() {
        document.querySelector('#btn').addEventListener('click', this.add)
    }

    add = () => {
        this.setState({counter: this.state.counter + 1})
        console.log('~~this.state.counter', this.state.counter)
    }

    render() {
        return <>
            

同步SetState

请观察控制台

} }

3. 写入setState的回调函数中

注意,只适用于class组件

export default class Pre04SetStateSync extends React.Component {
    state = {
        counter: 0
    }
    add = () => {
        this.setState({counter: this.state.counter + 1}, ()=>{
            console.log('~~this.state.counter', this.state.counter)
        })
    }
    render() {
        return <>
            

同步SetState

请观察控制台

} }

4. 连续setState的问题

注意,class组件和hooks都可以

如果将add改为先加1再加2,会发现代码只执行了最后一个加2,加1被忽略了,如:

const add = () => {
    setCounter(counter + 1)
    setCounter(counter + 2)
}

解决方法是将setState的参数写成函数形式

const add = () => {
    setCounter(counter => counter + 1)
    setCounter(counter => counter + 2)
}

5. 使用副作用useEffect

注意,只适用于hooks

export default function Pre04SetStateSync() {
    const [counter, setCounter] = useState(0)
    const add = () => {
        setCounter(counter + 1)
    }
    useEffect(() => {
        console.log({counter})
    }, [counter])
    
    return <>
        

同步SetState

请观察控制台

}

你可能感兴趣的:(前端,react,hooks,同步,javascript,前端)