当变量初始化为 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 会保留原始值。但是当我改变变量时,道具也会改变:
问题是对象分配是通过引用工作的,而且扩展语法只是将对象克隆了一层深,你需要更新你的对象,比如
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]
数组
我创建了一个变量并将其设置为等于一些道具。当我改变我的变量时,道具也改变了。如何在不更改 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 会保留原始值。但是当我改变变量时,道具也会改变:
问题是对象分配是通过引用工作的,而且扩展语法只是将对象克隆了一层深,你需要更新你的对象,比如
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]
数组