html table 正在无缘无故地复制默认值

html table is duplicating defaultValue's for no apparent reason

我有一些数据显示在 table 中。当我使用 JS 添加 table 数据单元格 (td) 时,前一个 table 数据单元格 (td) 的 defaultValue 和 innerText 被复制到新的 table 数据 (td) 中。我不明白为什么会这样?我只是添加了一个新的 html 元素,本质上,它与我要说的已经存在的元素无关。

 const [dataSet, setDataSet] = useState([
{
  City: "Amsterdam",
  Provence: "North-Holland"
},
{
  City: "Rotterdam",
  Provence: "South-Holland"
}
]);
    
  const newCity = () => {
    const city = [
      {
        City: "Groningen",
        Provence: "Groningen"
      }
    ];

    setDataSet(city);
  };
<button onClick={newCity}>Add city</button>

<table>
 <tr>
  <th>City</th>
  <th>Provence</th>
 </tr>
 {dataSet.map(city => (
  <tr>
   <td>
     <input defaultValue={city.City}/>
   </td>
   <td>
    <input defaultValue={city.Provence}/>
   </td>
 </tr>
 )}
</table>

因此,当我单击 'newCity button' 时,会添加一个新的 table 行 (tr),但不会使用正确的数据填充 table 数据单元格 (td) (城市:'Groningen',普罗旺斯:'Groningen') 它使用来自前一个 table 行 (tr) 的数据填充 td(城市:'Amsterdam',普罗旺斯:'North-Holland').这对我来说真的很奇怪,因为我只添加了一个新的 html 元素,它与 table 行 (tr) 无关,因为它在相同的 table 中。

这是一个代码框 link 以查看实际行为: https://codesandbox.io/s/dry-water-rss2m8?file=/src/App.js

为什么会这样?

您需要在项目上设置一个键

{dataSet.map((city) => (
          <tr key={city.City}>

... 等等

这里有两件重要的事情需要考虑。

首先,您的程序正在输出警告:

Warning: Each child in a list should have a unique "key" prop.

始终 处理警告。他们在那里是有原因的!

其次,您正在处理一个 默认(相对于 当前)值。


当您用新数组替换数组时,React 会生成新的 JSX 并将其与现有的 DOM 进行比较。

第一个 行具有相同(缺少)键,因此它更改了现有行的默认值。 (second 行不再存在,因此将其删除)。

通过以下方式更改默认值没有任何效果:输入 已经 有值,它们将继续显示。


您可以给生成的行键:

<tr key={something}>

…但你需要弄清楚那是什么东西。

您可能会使用城市名称,但它似乎是一条可能会更改的数据 — 因此更改城市名称会使它看起来像一个新行,而不是对现有行的更新。

您可以考虑在创建对象时使用 uuid module 生成唯一 ID。


您还可以通过传递值而不是默认值来进行输入 controlled。这将要求您在编辑时更新传递给它们的值。

首先,原生 Input 元素没有 defaultValue 属性。查看 MDN 中的属性列表。它只有值和占位符。

其次,如果要向数据集中添加新城市,必须将 city-object 合并到数组中,而不是替换它。

setDataSet(currentDataSet => {
  return [...currentDataSet, city]
})

我猜是因为你在使用不受控制的组件。

如果您希望输入值反映状态变化,您需要使用该值而不是默认值,并且您可能还需要一个 onChange 处理程序。

<input value={city.City} />