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

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

原文地址:https://www.cnblogs.com/chaoxiZ/p/9908830.html