首页 > 解决方案 > React useState 改变了我不变的初始状态

问题描述

我的selectItem事件改变了initialState我故意实现的,以保持不变。

Panel.js

import React, { useState } from "react";
import "./Panel.css";
import Item from "./Item";

const initialState = [
  { text: 1, isSelected: false },
  { text: 2, isSelected: false },
  { text: 3, isSelected: false },
  { text: 4, isSelected: false },
  { text: 5, isSelected: false }
];

export default function Panel() {
  const [items, setItems] = useState(initialState);

  const selectItem = k => {
    console.log(k);
    const updatedItems = [...initialState];
    updatedItems.find(item => item.text === k).isSelected = true;
    setItems(updatedItems);
  };

  return (
    <div className="Panel">
      {items.map(item => (
        <Item
          key={item.text}
          text={item.text}
          isSelected={item.isSelected}
          clicked={selectItem}
        />
      ))}
    </div>
  );
}

项目.js

import React from "react";
import "./Item.css";

export default function Item({ text, isSelected, clicked }) {
  return (
    <div className="Item" onClick={() => clicked(text)}>
      {isSelected ? <div style={{ backgroundColor: "red" }}>{text}</div> : text}
    </div>
  );
}

标签: reactjsuse-state

解决方案


这样看,你的数组是一个对象数组,每个索引(item)都是对某个特定对象的引用。

基本上,当您创建updatedItems数组时,您会将其所有引用分散到一个新的“引用对象的数组”中。因此,从技术上讲,您使用的是完全相同的对象。一旦你选择了一个并改变它,你就改变了同时引用initialStateitems引用的对象。

您正在做的是数组的浅层克隆(副本)。

如果您想进行深度克隆,一个简单的方法是:JSON.parse(JSON.stringify(initialState)).

您还可以使用 lodash/cloneDeep https://lodash.com/docs/4.17.15#cloneDeep等实用程序

但请记住,深度克隆也可能非常昂贵,而且并不总是理想的结果。


推荐阅读