首页 > 其他分享 >01-React-组件-setState

01-React-组件-setState

时间:2023-09-23 12:34:54浏览次数:38  
标签:01 return oldObj age React state setState

setState 是如何给 state 赋值的

  • 通过 Object.assign()
import React from 'react';

class Home extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            name: 'BNTang',
            age: 18
        }
        let oldObj = {name: 'BNTang', 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;

image-20220417232753576

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:

image-20220417233223604

为什么最终的一个值是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;

image-20220417234700880

那么为什么这样就可以解决从 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);

标签:01,return,oldObj,age,React,state,setState
From: https://www.cnblogs.com/lzAurora/p/17724197.html

相关文章

  • 01-React-组件-Ref
    React中获取元素的方式字符串对象回调函数官方文档:https://zh-hans.reactjs.org/docs/refs-and-the-dom.html#gatsby-focus-wrapper第一种传统方式(在React中及其不推荐)importReactfrom"react";classAppextendsReact.PureComponent{constructor(prop......
  • 01-React-组件-CSS模块化
    CssModule(推荐)React的脚手架已经内置了cssmodules的配置:.css/.less/.scss等样式文件都修改成.module.css/.module.less/.module.scss等;在以前我们的文件是这样的index.css如果使用了CSS的模块化之后,在之前的文件的基础上在加上.module即可,如,index.module.cs......
  • 01-React-生命周期-执行时机
    生命周期概述事物从生到死的过程,我们称之为生命周期什么是生命周期方法事物在从生到死过程中,在特定时间节点调用的方法,我们称之为生命周期方法例如像我们人类,从生到死的过程有这么几个特定的时间点,就是上,幼儿园,小学,中学...React组件生命周期方法组件从生到死的......
  • 01-React-父子组件通讯-函数式组件
    在了解父子组件通讯这个知识点的时候,首先要说明清楚一点内容就是什么是父组件什么是子组件,在上一篇React-组件开篇当中我们在App.js类组件当中使用到了其它的一些组件,那么App就是父组件,被App所使用的就是子组件,了解了什么是父子组件之后,介绍要来介绍一下它们之间该如何进......
  • 01-React-父子组件通讯
    父子组件通讯父组件将方法传递给子组件,在React当中也会将父组件传递的,数据和函数信息直接存放在子组件当中,的Props属性对象当中React的父子组件通讯的实现其实就是利用,函数的互相调用进行实现完成的Header.js:importReactfrom'react';import'./Header.css';impo......
  • 01-React-组件-TransitionGroup
    TransitionGroup的作用,博主用通俗易懂的话来讲就是一个一组元素添加动画,在我们的实际开发当中有时可能会有这么一个需求就是,在一个页面上,有添加和删除,在做这些操作的时候需要都带上动画,那么这个时候就可以使用TransitionGroup来快速实现。案例App.js:importReactfrom'rea......
  • P6667 [清华集训2016] 如何优雅地求和 -Binomial Sum
    题面有一个多项式函数\(f(x)\),最高次幂为\(x^m\),定义变换\(Q\):\[Q(f,n,x)=\sum_{k=0}^{n}f(k)\binom{n}{k}x^k(1-x)^{n-k}\]现在给定函数\(f\)和\(n,x\),求\(Q(f,n,x)\bmod998244353\)。出于某种原因,函数\(f\)由点值形式给出,即给定\(a_0,a_1,⋯,a_m\)共\(m+1\)个......
  • Flutter/Dart第01天:Dart安装和初体验
    本博客原地址:https://ntopic.cn/p/2023092301/Dart的安装方式有几种:一种是下载源代码,然后编译安装;一种是通过包管理工具进行安装。Dart官方网站分表列出了针对Windows、Linux和MacOS的安装方式:https://dart.dev/get-dart我下面在个人MacOS上介绍brew包管理工具安装方法和过程:......
  • React面试
    1.什么是虚拟DOM?虚拟DOM是真实DOM在内存中的表示,ul的表示形式保存在内存中,并且与实际的DOM同步,这是一个发生在渲染函数被调用和元素在屏幕上显示的步骤,整个过程被称为调和2.类组件和函数组件之间的区别是什么?类组件可以使用其他特性,如状态和生命周期钩子,并且他有this函数组件只......
  • 自我介绍102101631
    自我介绍我叫陈康杰,学号是102101631我来自fzu我平常喜欢看一些历史文我最喜欢的歌手是周杰伦我最喜欢的歌曲是《一路向北》食堂里我最喜欢的是烤盘饭(虽然每次吃饱都花了很多的币)......