关于React- Hooks使用


环境

"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 <>

        <h3>同步SetState</h3>

        <p>请观察控制台</p>

        <button onClick={add}>counter: {counter}</button>

    </>

}

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 <>

            <h3>同步SetState</h3>

            <p>请观察控制台</p>

            <button onClick={this.add}>counter: {this.state.counter}</button>

        </>

    }

}


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 <>

            <h3>同步SetState</h3>

            <p>请观察控制台</p>

            <button id='btn'>counter: {this.state.counter}</button>

        </>

    }

}


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 <>

            <h3>同步SetState</h3>

            <p>请观察控制台</p>

            <button onClick={this.add}>counter: {this.state.counter}</button>

        </>

    }

}


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 <>

        <h3>同步SetState</h3>

        <p>请观察控制台</p>

        <button onClick={add}>counter: {counter}</button>

    </>

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容