当变量初始化为 props 更改时,React props 意外更改

React props change unexpectedly when a variable initialized as props changes

我创建了一个变量并将其设置为等于一些道具。当我改变我的变量时,道具也改变了。如何在不更改 props 的情况下更改变量?

import React from 'react';
import { connect } from 'react-redux';

...

class TestApp extends React.Component {
    render() {
        var test = this.props.test;
        console.log("before change")
        console.log(test.name)
        console.log(this.props.test.name)

        // change the variable
        test.name[0] = 'pakpahan'


        console.log("after change")
        console.log(test.name)
        console.log(this.props.test.name)

        return (
            ...
        )
    }
}

...

const mapStateToProps = function (state) {
    return {
        test : {
            name : ['aldo', 'lino']
        }
    }
};


export default connect(mapStateToProps)(TestApp);

我已经尝试过使用其他人提供的一些解决方案

var test = {...this.props.test};

但是结果是一样的,道具还是变了

我预计变量会发生变化,而 props 会保留原始值。但是当我改变变量时,道具也会改变:

Screenshot

问题是对象分配是通过引用工作的,而且扩展语法只是将对象克隆了一层深,你需要更新你的对象,比如

render() {
    var test = {...this.props.test};
    console.log("before change")
    console.log(test.name)
    console.log(this.props.test.name)

    // change the variable
    const newName = [...test.name]
    newName[0] = 'Abc';
    newName[3] = 'GBG';
    test.name = newName;


    console.log("after change")
    console.log(test.name)
    console.log(this.props.test.name)

    return (
        ...
    )
}

扩展 Shubham 的回答,内存中只存储基元(int、string、bool、...)。 Non-primitives(数组、对象、函数)只存储指向内存的指针。

因此基元的行为与您期望的变量一样,因为它们实际上存储了值:

let a = 1;
let b = a;
b = 2;
console.log(a); // 1
console.log(b); // 2

而non-primitives实际上只存储了一个引用:

let x = [1, 2];
let y = x;
y[0] = 5;
console.log(x); //[5,2]

x 和 y 都存储指向数组在内存中的位置的指针。因此,当您更改 y 上的位置 [0] 时,x 也会在位置 [0] 处看到“5”。 x -> [5,2] <-y

https://medium.com/@junshengpierre/javascript-primitive-values-object-references-361cfc1cbfb0

Shubham(我认为)在内存中创建一个具有相同值的新 space。所以这两个变量会有不同的指针。

x = [1,2]; // x -> [1,2]
y = x;     // x -> [1,2] y -> [1,2]
y[0] = 5   // x -> [1,2] y -> [5,2]

对存储基元的对象执行此操作的另一种方法是创建一个新的 属性,这样您也可以保留旧值。

test = { 
    name : 'aldo'
}

test2 = test;
test2.newName = 'pakpahan';

console.log(test.name); // aldo
console.log(test2.newName) // pakpahan

但是,因为对象内部有一个数组,所以 运行 进入了另一个引用指针问题。如果要在保留原始数组的同时编辑新数组,则需要创建一个新指针。

尝试:{...this.props.test} 对象或 [...this.props.test] 数组