React 如何克隆道具

React how to clone props

我在学习

我的组件中的这个函数有问题:

...
export default function Main(props) {
...
...
...
const deleteMessage = (index) => {
        let test = props.data.contacts;
        // let test2 = { ...props.data.contacts}; Also tried with this
        test[currentContact].messages.splice(index, 1);
        // props.setData({ ...props.data, test }) this is commented and should't be executed
    }
return (...<JSX Elements>...)
}

当我 运行 <li onCLick={() => deleteMessage(index)}> Delete this message </li> 更改是在父组件的状态上执行的。

虽然在本示例代码中注释掉了props.setData(),但是props.data仍然受到该函数变化的影响

如何在新对象中克隆 props.data 并只处理这个对象,而不更改 props.data?

克隆是正确的方法,我们通常希望避免直接改变数组/对象。

我认为克隆数组或对象的最常见的现代方法是通过 spread operator.

将其内容传播到新变量中

例子-

const originalArray = [1, 2, 3, 4];
const originalObject = {
  'a': 1,
  'b': 2,
  'c': 3,
  'd': 4,
};

const newArray = [...originalArray, 5, 6];
const newObject = {
  ...originalObject,
  'e': 5,
  'f': 6,
};

console.log(newArray); // [1, 2, 3, 4, 5, 6]
console.log(newObject); // {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}

如您所见,它充当数组/对象中的成员,本质上是在创建新变量的同时传播原始变量,而不是对原始变量的引用。

更新状态时,请确保嵌套结构的每个部分都被克隆,直到您到达要更新的实际内容。

test[currentContact].messages.splice(index, 1);

这很糟糕,因为 splice 修改了 messages 数组。

事实上 test[currentContact].messages 本身就很糟糕,因为 test[currentContact] 正在发生变异。

// let test2 = { ...props.data.contacts}; Also tried with this

对象和数组扩展语法可用于克隆和防止变异,但这里也要确保先克隆 props.data,然后再克隆 contacts


不可变地更新数组和对象的示例:

const bla = {
  foo: {
    bar: [1]
  }
}

// here's how you can update `bla` immutably if you want to add an element to the nested array
const clonedBla = { ...bla,
  foo: {
    ...bla.foo,
    bar: [...bla.foo.bar, 2]
  }
}
console.log(bla, clonedBla)

const bla = {
  foo: [{
      a: "a",
    },
    {
      b: "b",
      arr: [1, 2],
    },
  ],
};

// if we want to remove the second element of `bla.foo[1].arr`
const updatedBla = {
  ...bla,
  foo: bla.foo.map((el, index) =>
    index === 1 ?
    {
      ...el,
      arr: el.arr.filter((_, iIndex) => iIndex !== 1),
    } :
    el
  ),
};
console.log(updatedBla)