【问题标题】:React useState returns old valueReact useState 返回旧值
【发布时间】:2020-12-14 00:01:11
【问题描述】:

在下面的示例中,我渲染了三个项目:1、2、3。我单击项目 3 将其删除,但屏幕上剩下的是项目 2 和 3 而不是只有 1 和 2,因为项目 3 应该是删除。为什么不删除第 3 项?

这是一个代码框链接,点击 3 将删除它:https://codesandbox.io/s/eager-currying-1bxnb?file=/src/App.js

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

export default function App() {
  const [items, setItems] = useState(data);

  const onDelete = (id) => {

    //LOGGING
    console.log(`^^^^^^^^^^BEFORE DELETING^^^^^^^^^^^^^^^^`)
    items.forEach( i => console.log(i.title))
    console.log(`-----------------------------------------`)

    //LOGIC
    let filteredItems = items.filter((c) => c.id != id);
    setItems([...filteredItems]);

    //LOGGING
    console.log(`^^^^^^^^^^AFTER DELETING^^^^^^^^^^^^^^^^`)
    filteredItems.forEach( i => console.log(i.title))
    console.log(`-----------------------------------------`)
  };

  return (
    <div>
      {items.map((i) => (
        <Item id={i.id} title={i.title} onDelete={onDelete} />
      ))}
    </div>
  );
}

const data = [
  {
    id: 3,
    uuid: "dbc74622-7002-41d2-9d89-e3d0d4558d25",
    title: "Item 3"
  },
  {
    id: 2,
    uuid: "c7ac4c96-c1e0-45a4-a739-6ca4ad483b68",
    title: "Item 2"
  },
  {
    id: 1,
    uuid: "48c90e0b-5b09-4583-8665-1f3d6f9df5f1",
    title: "Item 1"
  }
];

const Item = ({ id, title, onDelete }) => {

  console.log(`Rendering Item ${title}`)
  const [inputTitle, setTitle] = useState(title);
  console.log(`Value set in useState ${inputTitle}`)
  // ^ this is where the problem occurs even though I set "Item 2", this returs "Item 3"

  return (
    <div
      onClick={() => {
        onDelete(id);
      }}
      key={id}
    >
      <h3>{inputTitle}</h3>
    </div>
  );

};

【问题讨论】:

  • 您能解释一下为什么订单很重要吗?如果我从数组中删除了一个项目,它不应该存在。

标签: reactjs react-hooks use-state


【解决方案1】:

key 属性应该放在 items.map() 回调中的 &lt;Item&gt; 组件上,而不是放在没有兄弟姐妹的 &lt;div&gt; 元素上。这是必要的,以便 React 可以确定虚拟 DOM 中的哪个 Item 实例与您的 items 数组的每个相应元素相关联。

附带说明一下,在调用setItems() 时不需要传播filteredItems,因为items.filter() 方法已经返回了一个新的数组实例,所以setItems(filteredItems); 就足够了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-08
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多