如果没有机会创建唯一密钥怎么办?

时间:2020-05-22 09:59:19

标签: javascript reactjs react-hooks react-key-index

我有一个复杂的数据集,因此我将显示一个非常简化的版本作为示例。

输入数据:

const data = [
  {
    type: "input",
    caption: "Name",
    defaultValue: "John Smith"
  },
  {
    type: "input",
    caption: "Name",
    defaultValue: "John Smith"
  },
  {
    type: "input",
    caption: "Name",
    defaultValue: "John Smith"
  },
  {
    type: "input",
    caption: "Name",
    defaultValue: "John Smith"
  },
  {
    type: "input",
    caption: "Name",
    defaultValue: "John Smith"
  }
];

阵列的每个项目都是可移动的。原来是这样的。

enter image description here

有几个条件。我不应该修改数据数组,所以我创建了一个深拷贝。在副本内部,我也只能删除元素,但不能修改其属性。因此,每个元素都必须具有带有新值的局部状态。

工作示例:

function App() {
  const [mainData, setMainData] = useState(deepCopy(data));

  return (
    <React.Fragment>
      {
        mainData.map((item, i) => {
          return (
            <Input {...item} key={i} num={i} setMainData={setMainData}/>
          )
        })
      }
    </React.Fragment>
  )
}

const Input = (props) => {
  const [value, setValue] = useState(props.defaultValue);

  const deleteElem = () => {
    props.setMainData((mainData) => {
      return [...mainData.filter((_, ind) => ind !== props.num)];
    });
  };

  return (
    <div>
      <div>
        <div>{`${props.caption}:`}</div>
        <input value={value} onChange={(e)=>setValue(e.target.value)}/>
      </div>
      <button onClick={deleteElem}>delete</button>
    </div>
  )
};



const deepCopy = (aObject) => {
  if (!aObject) {
    return aObject;
  }
  let value;
  let bObject = Array.isArray(aObject) ? [] : {};

  for (const key in aObject) {
    value = aObject[key];
    bObject[key] = (typeof value === "object") ? deepCopy(value) : value;
  }

  return bObject;
};

如果您尝试不删除最后一个元素,则(由于键的原因)输入元素的值将混合在一起。 我该怎么办?

2 个答案:

答案 0 :(得分:3)

通过deepCopy,您可以在初始化状态时为每个项目添加唯一的ID。完成后,您可以利用该ID作为键将其传递给Input元素

import {uuid} from 'uuidv4';
function deepCopyAndAddId = () => {
   let newData = deepCopy(data);
   newData = newData.map((item, index) => ({...item, id: uuid()})); 
}
function App() {
  const [mainData, setMainData] = useState(deepCopyAndAddId);

  return (
    <React.Fragment>
      {
        mainData.map((item, i) => {
          return (
            <Input {...item} key={item.id} num={i} setMainData={setMainData}/>
          )
        })
      }
    </React.Fragment>
  )
}

答案 1 :(得分:1)

要在代码中进行最少的更改-永远不要删除deleteElem中的项目,而是向其中添加标志deleted

渲染项目时,为<Fragment>项目显示deleted