React - 更新状态(对象数组)。我需要深度复制数组吗?

IT技术 javascript reactjs react-hooks
2021-04-16 04:13:55

我有以下几点state

const[images,setImages] = useState([
  {src: 'stringSRC1', selected: false},
  {src: 'stringSRC2', selected: false},
  {src: 'stringSRC3', selected: false}
]);

我正在使用以下代码更新它(切换选定状态):

function handleImageClick(index) {
  props.setImages((prevState)=>{
    const aux = Array.from(prevState);
    aux[index].selected = !aux[index].selected;
    return aux;
  });
}

它按预期工作。但我想到了一件事。

当我从 复制数组时prevState我正在创建一个新数组,但对象(存储为引用)将保持不变。我已经测试过了,当你像这样复制数组时,它们不会改变。

问题

这是一种不好的做法吗?我是否应该费心深复制数组,就像创建一个新数组并创建全新的对象一样?或者这样就好了?

2个回答

不,这就是它应该如何工作。是的,对象没有改变,但这里重要的是数组发生了变化。当事情发生变化时,React 在 DOM 和虚拟 DOM 之间进行浅层比较。一旦将新数组与旧数组进行比较,就会检测到更改,数组本身的内容并不重要。

是的,如果你想避免副作用,你必须深度克隆。

在您的功能中:

function handleImageClick(index) {
  props.setImages((prevState)=>{
    const aux = Array.from(prevState);
    aux[index].selected = !aux[index].selected;
    return aux;
  });
}

当您使用时,Array.from您将获得对存储的对象的引用,因此您的 prevState 被修改。

看到这个:

setTest(prevState => {
      console.log("PrevState", prevState);
      const b = Array.from(prevState);
      b[0].a = b[0].a + 1;
      return b;
    });

你可以在这里测试:

https://codesandbox.io/embed/exciting-mcnulty-6spdh?fontsize=14

您将看到 prevState 具有下一个值,因此您丢失了 prevState 值。

想象一下,您想在代码中执行此操作:

function handleImageClick(index) {
      props.setImages((prevState)=>{
        const aux = Array.from(prevState);
        aux[index].selected = !aux[index].selected;
        aux[index + 1].selected = prevState[index].selected;
        return aux;
      });
    }

aux[index + 1].selected = prevState[index].selected; 被打破!!

所以你需要对数组进行深度复制来避免这种事情。

你可以做: const aux = JSON.parse(JSON.stringify(prevState));

因为如果这是唯一的问题,我认为不值得为了这种可能性而将所有内容都作为一种习惯进行深度复制。我可以将该特定属性保存到辅助变量中,以便在更改代码后进一步访问代码。你怎么认为?仅针对这种特定情况是否值得深度复制所有内容?
2021-06-01 04:13:55
谢谢!我同意如果我想访问我刚刚更改的对象属性,该信息将无法访问并完全消失。但除此之外,您还看到其他问题吗?因为一旦setState()完成运行,该prevState对象将不再可用。下一次,它将是一个不同的对象。IE:我唯一担心的应该是prevState当前正在进行的执行期间的值setState()
2021-06-06 04:13:55