• 在React开发中遇到的问题——数组引用赋值


    在React开发中遇到了一个问题:
    需求是在一个选择组件中选择数据mydata数组,确定后将mydata数组返回到父组件,再次打开该选择组件时,从父组件获取之前选择的数据mydata并显示为已选择。

        /* 打开选择组件 */
        showModal = () => {
            this.setState({
                comVisible: true
            });
            const { mydata } = this.props;
            this.setState({
                mydata: mydata
            });
            console.log(this.state.mydata);
            this.onChange();
        }
    
        /* 确定-将data返回父组件 */
        handleOk = () => {
            if (this.state.mydata.length > 0) {
                this.setState({
                    comVisible: false
                });
                // 返回父组件data
                this.props.getMyData({
                    mydata: this.state.mydata,
                    ...
                });
            } else {
                message.error("data is null");
            }
        }
    
        /* 取消-不对data做操作 */
        handleCancel = () => {
            this.setState({
                comVisible: false
            });
        }
        /* 选择data */
        onChange = (mydata) => {
            let mydata = this.state.mydata;
            Object.keys(otherdata).forEach((title) => {
               ... 
               // 对mydata做一些改变
            });
            this.setState({
                mydata
            });
        }
    

    大概流程如下:
    流程.png

    按照逻辑,在选择组件中选择mydata,触发onChange事件,将此时改变的mydata设置为state.mydata,点击确定后触发handleOk函数,将state.mydata传给父组件。但若点击取消,则触发handleCancel,不做任何操作。
    那么问题来了,我点击了取消,再次打开选择组件,从父组件取mydata的值,取到的是点击取消之前选择的mydata值。按理说点击了取消不做操作,该值是不会传给父组件的,但是为什么从父组件会取到改变后的值呢?

    经过一系列尝试后发现,问题的原因在于数组的表现形式就是内存中的一段连续的内存地址,数组名称其实就是连续内存地址的首地址。onChange中对mydatastate.mydata的改变会直接改变该数组所指向的地址中的数据,而父组件中的mydata也是指向该数组的,所以一旦state.mydata发生改变,即使不将改变后的mydata传给父组件,父组件的mydata也会改变。

    修改:给父组件传值时使用中间变量,并且数组赋值时,使用先结构再赋值的方式生成新的数组。

        /* 打开选择组件 */
        showModal = () => {
            this.setState({
                comVisible: true
            });
            const { mydata } = this.props;
            this.setState({
                mydata: mydata
            });
            this.onChange();
        }
    
        /* 确定-将data返回父组件 */
        handleOk = () => {
            if (this.state.mydata.length > 0) {
                // 返回父组件data,改变后的中间变量
                this.props.getMyData({
                    mydata: this.state.tempdata,
                    ...
                });
            } else {
                message.error("data is null");
            }
        }
    
        /* 取消-不对data做操作 */
        handleCancel = () => {
            ...
        }
        /* 选择data */
        onChange = (mydata) => {
            // 改变赋值方式
            let mydata = [];
            mydata.push(...this.state.mydata);
            Object.keys(otherdata).forEach((title) => {
               ... 
               // 对mydata做一些改变
            });
            // 使用中间变量,不直接修改state.mydata
            this.setState({
                tempdata: mydata
            });
        }
    

    总结:

    在JS中,
    数组和对象是地址型变量
    数组和对象是地址型变量
    数组和对象是地址型变量

    基础知识一定时刻记在脑子里。。。

  • 相关阅读:
    慢sql
    drf 和django 字段参数解析
    django uwsgi
    django 中间件原理图和实现方法
    解决 控制台console导入模型报错 django.core.exceptions.ImproperlyConfigured: Requested setting INSTALLED_APPS, but settings are not configured.
    版本控制器 django全局和局部配置
    极客论坛Cpu瓶颈定位思路
    jmeter grpc 自定义开发java请求案例
    论文阅读笔记四十七:Generalized Intersection over Union: A Metric and A Loss for Bounding Box Regression(CVPR2019)
    论文阅读笔记四十六:Feature Selective Anchor-Free Module for Single-Shot Object Detection(CVPR2019)
  • 原文地址:https://www.cnblogs.com/chaoxiZ/p/9908830.html
Copyright © 2020-2023  润新知