最近,我使用数组值而不是像下面这样的键的索引犯了一个小错误:
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
function NamesView(props: {names: string[], setNames(l: string[]) : void}) {
const {names, setNames} = props;
function setName(index: number, name: string) {
setNames(names.map((n, i) => i===index ? name : names[i]));
}
return <div>
{/***** THE key IS WRONG!!! */ }
{names.map((n, i) => <input key={n} value={n} onChange={e => setName(i, e.target.value)}/>)}
</div>;
}
function MainView() {
const [names, setNames] = useState(() => ['one', 'two']);
return <NamesView names={names} setNames={setNames}/>
}
ReactDOM.render(<MainView/>, document.getElementById('root'));
在这里,使用key={i}
是正确的。我不了解错误代码的行为:每个输入只能编辑一次。您可以添加或删除字符,也可以粘贴某些东西,并且可以使用,但是所有后续更改都会被忽略-直到您更改焦点为止。
有人可以解释为什么吗?
键用于列表,以帮助React识别哪些项目已更改,添加或删除。在您的情况下,您使用名称作为键,因此,每当您更新输入字段的值时,键也会被更新。 React将其检测为被删除的元素,并添加了新元素。
因此,React实际上不只是更新值,而是删除了输入字段,然后再次添加了输入字段,这就是为什么输入在更新其中一个输入之后失去焦点的原因。
当通过names
映射时,这是输入值的数组。您正在通过以下方式呈现输入。
return (
<div>
{/***** THE key IS WRONG!!! */}
{names.map((n, i) => (
<input key={n} value={n} onChange={(e) => setName(i, e.target.value)} />
))}
</div>
);
一旦更改输入,setNames
就会通过setName
通过onChange
触发。
这意味着react
现在将检查生成的新项目。
因为key={n}
会更改输入本身,即会在dom中生成一个新的输入元素并立即对其进行更新,这就是为什么每次更改它都会失去焦点。
您可以在这里阅读有关键的更多信息: