我目前遇到了这个问题,我有一个选择字段依赖于另一个字段。
MUI: You have provided an out-of-range value `1` for the select component.
Consider providing a value that matches one of the available options or ''.
这是我的两个领域
<Select
labelId="originEntityLabel"
id="originEntityField"
displayEmpty
defaultValue={entityForm.originEntity?.name ?? ""}
label="Entity"
onChange={(event: SelectChangeEvent) => onFieldChangeEntity(event.target.value, "entity")}
>
<MenuItem key="none" value="">
--None--
</MenuItem>
{entityList.map((entity) => {
return (
<MenuItem key={entity.name} value={entity.name}>
{entity.name}
</MenuItem>
)
})}
</Select>
这是我遇到问题的“选择”字段。
<Select
labelId="startTierFieldLabel"
id="startTierField"
defaultValue={String(entityForm.startTier) ?? ""}
label="Start Tier"
onChange={(event: SelectChangeEvent) => onFieldChange(event.target.value, "tier")}
>
{tierRange && tierRange.map((tier) => {
return (
<MenuItem key={tier} value={tier}>
Tier {tier}
</MenuItem>
)
})}
</Select>
tierRange 通过状态控制
const [tierRange, setTierRange] = useState<number[]>(range(0, 11));
这是我的两个关于改变的方法
const onFieldChange = (value: any, field: string) => {
const currEntity = entityForm as Entity;
currEntity[field as keyof Entity] = value as never;
console.log('field change', currEntity);
setEntityForm(currEntity);
}
const onFieldChangeEntity = (value: any, field: string) => {
console.log('field change entity', value);
const entityLookup = entityList.find(entity => entity.name === value);
const currEntity = entityForm as Entity;
const minTier = entityLookup ? entityLookup.startTier + 1 : 0;
currEntity.originEntity = entityLookup;
currEntity.startTier = Math.max(currEntity.startTier, minTier);
setEntityForm(cloneDeep(currEntity));
setTierRange(range(minTier, 11));
}
我不确定为什么会出现这个错误。当我尝试记录信息时,currEntity 具有正确的 startTier,但我不确定为什么它在表单中没有正确反映。
我还尝试在entityForm状态上创建一个完全独立的useEffect,然后更新tierRange
useEffect(() => {
console.log('in use effect entity form');
const minTier = entityForm.originEntity ? entityForm.originEntity.startTier + 1 : 0;
setTierRange(range(minTier, 11));
}, [entityForm]);
但这也无济于事。我对 typescript 和 mui 比较陌生,所以我不确定是什么原因造成的。 (另外,我愿意采用一种更好的方法来完成我正在尝试的事情 - 基本上让 1 个字段具有另一个字段的依赖值,如果知道的话也很好。)
TL; DR:使用第二个
value
的 <Select>
属性将其作为 受控 输入,并在其选项更改时重置它(至少当其当前 value
不再是一部分时)其新选项)。
<Select>
(label="Start Tier"
)有一些value
(最初来自其defaultValue
,或其第一个选项值来自tierRange
)<Select>
(label="Entity"
) 中选择某个选项,触发其 onChange
回调,此处为 onFieldChangeEntity
,这会更改第二个选择的 tierRange
选项以及 entityForm.startTier
defaultValue
属性,因此它仅在最初影响其 value
value
不再是其选项的一部分,您会收到超出范围的错误在步骤 2 中,您需要在更改第二个选择的 tierRange
选项的同时重置其
值(不仅仅是默认值),因此它必须是一个 受控 输入元素。至少如果它的当前值不再是新选项的一部分(但您可以选择在所有情况下重置它):
// value of 2nd Select (start tier)
const [selectedTier, setSelectedTier] = useState(String(entityForm.startTier) ?? tierRange[0]);
// onChange callback of the 2nd Select
const onFieldChange = (value: any, field: string) => {
// etc.
setSelectedTier(value); // We now have to explicitly control the Select value
}
// onChange callback of 1st Select (entity)
const onFieldChangeEntity = (value: any, field: string) => {
// etc.
const newTierRange = range(minTier, 11);
setTierRange(newTierRange);
// Reset the value of the 2nd Select (start tier),
// at least if its current value is no longer in tierRange
if (!newTierRange.includes(selectedTier)) {
setSelectedTier(minTier); // or currEntity.startTier
}
}
<Select
value={selectedTier} // Use the Select value prop to turn it into a controlled input
label="Start Tier"
onChange={(event: SelectChangeEvent) => onFieldChange(event.target.value, "tier")}
>
{/* tierRange options */}
</Select>