我有一个 React 组件,它有多个
<select>
(不是反应选择)元素。根据其中一项道具仅渲染一个 <select>
:
class SelectGroup extends Component {
...
render () {
let activeSelect
switch (this.props.foo) {
case 'select1':
activeSelect = <select id="select1">
<option value="1a" selected>1 A</option>
<option value="1b">1 B</option>
<option value="1c">1 C</option>
</select>
break
case 'select2':
activeSelect = <select id="select2">
<option value="2a" selected>2 A</option>
<option value="2b">2 B</option>
<option value="2c">2 C</option>
</select>
break
...
}
return activeSelect
}
...
}
(出于我们的目的,假设
SelectGroup
嵌套在另一个组件内,当单击按钮时,该组件会更改 foo
属性。)
我想要的是,每当我们更改正在渲染的
<select>
时(每当道具<select>
更改时),默认情况下都会选择每个foo
的第一个选项。正如您所看到的,我给了每个 <select>
的第一个选项 selected
属性,根据 this Documentation,应该将其设为默认选项。然而,这不是我看到的行为。发生的事情是这样的:
select1
。我从下拉列表中选择选项 1b
。select2
。2a
,因为它具有 selected
属性。但是,却选择了 2b
。2c
。select1
。1a
被选中。但是,却选择了 1c
。它似乎完全忽略了
selected
属性,相反,它看起来像是从列表中选择与更改渲染哪个 <select>
之前选择的选项相对应的选项。
奇怪的是,如果我从除
selected
之外的所有<select>
元素中删除select1
属性,那么select1
将按预期运行:当我切换到select1
时,无论什么,它都会始终显示选项1a
之前已选择,但 select2
显示的选项将继续取决于切换到之前选择的内容。所以就好像 selected
仅在仅使用一次时才有效,但我不明白为什么会这样,因为它只应用于每个 <select>
的一个选项。
每当我在渲染的
<select>
之间切换时,如何才能选择第一个选项?
尝试为每个选择添加唯一的
key
:
switch (this.props.foo) {
case 'select1':
activeSelect = <select key="select1" id="select1">
<option value="1a" selected>1 A</option>
<option value="1b">1 B</option>
<option value="1c">1 C</option>
</select>
break
case 'select2':
activeSelect = <select key="select2" id="select2">
<option value="2a" selected>2 A</option>
<option value="2b">2 B</option>
<option value="2c">2 C</option>
</select>
break
...
当条件翻转时,这将强制完全删除并随后追加。当您从一种切换到另一种时,最有可能发生的情况是,React 的 VDOM 启动并修改现有的选择而不是替换它。由于(相当奇怪和古老的)DOM 行为,旧选择的选定值被保留。
通过使用独特的
key
,它将迫使React完全重新渲染整个节点,并在此过程中丢弃内存中任何选定的值状态。
顺便说一句,你所做的有点奇怪——几乎肯定有更好的方法,但我对你的用例了解不够。您可能想有条件地内联渲染它们,这意味着在 React 所持有的组件的内部表示中,它们是 2 个独立的节点:
return <>
{this.props.foo === "select1" &&
<select id="select1">
<option value="1a" selected>1 A</option>
<option value="1b">1 B</option>
<option value="1c">1 C</option>
</select>
}
{this.props.foo === "select2" &&
<select id="select1">
<option value="1a" selected>1 A</option>
<option value="1b">1 B</option>
<option value="1c">1 C</option>
</select>
}
</>
您可能会想“这有什么不同”。好吧,不活动的将呈现 false(不呈现任何内容)。但它呈现“false”意味着该节点单独表示为该值,而不是填充到一个值中,这就是为什么 Reacts vdom 认为它是完全相同的节点。