• 在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中,
    数组和对象是地址型变量
    数组和对象是地址型变量
    数组和对象是地址型变量

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

  • 相关阅读:
    linux 文件系统(inode和block)
    vue状态管理vuex从浅入深详细讲解
    小白都能看懂的vue中各种通信传值方式,附带详细代码
    CSS3移动端vw+rem不依赖JS实现响应式布局
    JavaScript原生封装ajax请求和Jquery中的ajax请求
    永久解决Sublime包管理package control 打开install package报错 There are no packages available for installation
    从GitLab上创建分支本地拉取项目和提交项目详解
    前端路由的两种实现方式,内附详细代码
    几个例子理解浅拷贝和深拷贝
    讲解JavaScript中对闭包的理解
  • 原文地址:https://www.cnblogs.com/chaoxiZ/p/9908830.html
Copyright © 2020-2023  润新知