React-组件-setState

简介: React-组件-setState

setState 是如何给 state 赋值的


  • 通过 Object.assign()
import React from 'react';
class Home extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            name: 'yangbuyiya',
            age: 18
        }
        let oldObj = {name: 'yangbuyiya', age: 18};
        let newObj = {age: 666};
        let obj = Object.assign({}, oldObj, newObj);
        console.log(obj);
    }
    render() {
        return (
            <div>
                <p>{this.state.name}</p>
                <p>{this.state.age}</p>
                <button onClick={() => {
                    this.btnClick()
                }}>按钮
                </button>
            </div>
        )
    }
    btnClick() {
        this.setState({
            age: 666
        });
    }
}
class App extends React.Component {
    render() {
        return (
            <div>
                <Home/>
            </div>
        )
    }
}
export default App;




state 合并现象


  • 因为 setState 会收集一段时间内所有的修改操作,然后在统一的执行,再更新界面
  • 所以就出现了 state 的合并现象

首先来看一个案例,然后引出这个 state 的合并场景先如下:

import React from 'react';
class Home extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            age: 0
        }
    }
    render() {
        return (
            <div>
                <p>{this.state.age}</p>
                <button onClick={() => {
                    this.btnClick()
                }}>按钮
                </button>
            </div>
        )
    }
    btnClick() {
        this.setState({
            age: this.state.age + 1
        });
        this.setState({
            age: this.state.age + 1
        });
        this.setState({
            age: this.state.age + 1
        });
        console.log(this.state.age);
    }
}
class App extends React.Component {
    render() {
        return (
            <div>
                <Home/>
            </div>
        )
    }
}
export default App;

然后查看结果发现居然是 1:

为什么最终的一个值是1, 不是 3 呢是吧,我明明是进行增加了 3 次加 1 的操作,因为 setState 默认是一个异步的方法, 默认会收集一段时间内所有的更新, 然后再统一更新, 所以就导致了最终的一个值是 1, 不是 3,博主可以大致的提供一下它底层的实现代码这样可以更加的让你对 setState 有更深层次的理解,如下:

let oldObj = {age: 0};
let stateList = [
    // 演变过程1
    // {age: oldObj.age + 1},
    // {age: oldObj.age + 1},
    // {age: oldObj.age + 1},
    // 演变过程2
    // {age: 0 + 1},
    // {age: 0 + 1},
    // {age: 0 + 1},
    // 演变过程3
    {age: 1},
    {age: 1},
    {age: 1}
];
stateList.forEach((newObj) => {
    // 演变过程1
    // Object.assign({}, {age: 0}, {age: 1}); // {age: 1}
    // 演变过程2
    // Object.assign({}, {age: 1}, {age: 1}); // {age: 1}
    // 演变过程3
    // Object.assign({}, {age: 1}, {age: 1}); // {age: 1}
    oldObj = Object.assign({}, oldObj, newObj);
});
console.log(oldObj);




解决 state 合并现象


第一种方案就是前面所说的通过 setState 方法的第二个参数, 通过回调函数拿到更新之后的值,然后在根据该值在进行加一操作如下:

import React from 'react';
class Home extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            age: 0
        }
    }
    render() {
        return (
            <div>
                <p>{this.state.age}</p>
                <button onClick={() => {
                    this.btnClick()
                }}>按钮
                </button>
            </div>
        )
    }
    btnClick() {
        this.setState({
            age: this.state.age + 1
        }, () => {
            this.setState({
                age: this.state.age + 1
            }, () => {
                this.setState({
                    age: this.state.age + 1
                });
            });
        });
        console.log(this.state.age);
    }
}
class App extends React.Component {
    render() {
        return (
            <div>
                <Home/>
            </div>
        )
    }
}
export default App;


但是上面的代码存在弊端,层级结构比较深,以后维护比较不友好,所以说 React 也考虑到了这一点,所以这里就引出了第二种解决方案,通过 setState 的第一个参数来进行解决,第一个参数除了可以传递一个对象,其实还可以传递一个回调函数,回调函数有两个默认的参数第一个就是上一次更新的最新的值,然后我们可以在该回调函数中就可以直接拿到最新的值,就不会出现合并的现象了。

import React from 'react';
class Home extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            age: 0
        }
    }
    render() {
        return (
            <div>
                <p>{this.state.age}</p>
                <button onClick={() => {
                    this.btnClick()
                }}>按钮
                </button>
            </div>
        )
    }
    btnClick() {
        this.setState((preState, props) => {
            return {age: preState.age + 1};
        });
        this.setState((preState, props) => {
            return {age: preState.age + 1};
        });
        this.setState((preState, props) => {
            return {age: preState.age + 1};
        });
        console.log(this.state.age);
    }
}
class App extends React.Component {
    render() {
        return (
            <div>
                <Home/>
            </div>
        )
    }
}
export default App;


那么为什么这样就可以解决从 0 变为 3 呢,这里也提供出它底层的实现,和演变过程,可以更深层次的加深理解:

let oldObj = {age: 0};
let stateList = [
    (preState) => {
        return {age: preState.age + 1}
    },
    (preState) => {
        return {age: preState.age + 1}
    },
    (preState) => {
        return {age: preState.age + 1}
    },
];
stateList.forEach((fn) => {
    // 演变过程1
    // {age: 1}
    // 演变过程2
    // {agg: 2}
    // 演变过程3
    // {agg: 3}
    let newObj = fn(oldObj);
    // 演变过程1
    // {age: 0} {age: 1} / {age: 1}
    // 演变过程2
    // {age: 1} {age: 2} / {age: 2}
    // 演变过程3
    // {age: 2} {age: 3} / {age: 3}
    oldObj = Object.assign({}, oldObj, newObj);
});
console.log(oldObj);





最后


本期结束咱们下次再见👋~

🌊 关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ 💗

相关文章
|
6月前
|
设计模式 前端开发 数据可视化
【第4期】一文了解React UI 组件库
【第4期】一文了解React UI 组件库
351 0
|
6月前
|
存储 前端开发 JavaScript
【第34期】一文学会React组件传值
【第34期】一文学会React组件传值
72 0
|
6月前
|
前端开发
【第31期】一文学会用React Hooks组件编写组件
【第31期】一文学会用React Hooks组件编写组件
74 0
|
6月前
|
资源调度 前端开发 JavaScript
React 的antd-mobile 组件库,嵌套路由
React 的antd-mobile 组件库,嵌套路由
119 0
|
2月前
|
前端开发 JavaScript
学习react基础(3)_setState、state、jsx、使用ref的几种形式
本文探讨了React中this.setState和this.state的区别,以及React的核心概念,包括核心库的使用、JSX语法、类与函数组件的区别、事件处理和ref的使用。
63 3
学习react基础(3)_setState、state、jsx、使用ref的几种形式
|
5月前
|
前端开发
前端React篇之React setState 调用的原理、React setState 调用之后发生了什么?是同步还是异步?
前端React篇之React setState 调用的原理、React setState 调用之后发生了什么?是同步还是异步?
|
6月前
|
存储 前端开发 中间件
React组件间的通信
React组件间的通信
50 1
|
6月前
|
前端开发 JavaScript API
React组件生命周期
React组件生命周期
116 1
|
6月前
|
存储 前端开发 JavaScript
探索 React Hooks 的世界:如何构建出色的组件(下)
探索 React Hooks 的世界:如何构建出色的组件(下)
探索 React Hooks 的世界:如何构建出色的组件(下)
|
6月前
|
缓存 前端开发 API
探索 React Hooks 的世界:如何构建出色的组件(上)
探索 React Hooks 的世界:如何构建出色的组件(上)
探索 React Hooks 的世界:如何构建出色的组件(上)
下一篇
无影云桌面