如何从外部覆盖内部组件状态
How to overwrite internal component state from the outside
我有一个相当简单的 NumberInput
component/control 用 useState
处理它的内部状态(它的当前值)。 “外部世界”对此状态不感兴趣,但仅通过回调函数 onSubmit
接收更新,该回调函数在输入和模糊时调用。
我还有一个名为 MinMaxNumberInputs
的组件,它由 2 NumberInput
组成。这 2 个 NumberInput
彼此之间一无所知,父 MinMaxNumberInputs
必须处理一些“值同步”,例如确保 min <= max 等
这最后一部分是我有点卡住的地方,因为我不知道如何在需要时“强制设置”或从 MinMaxNumberInputs
覆盖 NumberInput
的内部状态.
可能最好通过代码解释:
NumberInput.tsx
// ...
type NumberInputProps = {
value: number;
onSubmit: (value: number) => void;
};
export default function NumberInput(props: NumberInputProps) {
// [1] props.value is obviously only applied on creation.
// Future changes have no effect.
const [value, setValue] = useState(props.value);
// Called on enter & blur
const submitValue = () => props.onSubmit(value);
// ...
return <input value={value} {/* ... */} />;
}
MinMaxNumberInputs.tsx
// ...
export const MinMaxValueInput = () => {
// Only for simpler showcasing, using global redux state in real world...
const [minValue, setMinValue] = useState(0);
const [maxValue, setMaxValue] = useState(0);
const onMinValueChanged = (newMinValue: number) => {
// [2] Ensure that entered value (min here) stays the same but adjust max if required
// ??? How to set adjusted value in max NumberInput ???
const newMaxValue = Math.max(newMinValue, maxValue);
setMinValue(newMinValue);
setMaxValue(newMaxValue);
};
const onMaxValueChanged = (newMaxValue: number) => {
// [3] Ensure that entered value (max here) stays the same but adjust min if required
// ??? How to set adjusted value in min NumberInput ???
const newMinValue = Math.min(minValue, newMaxValue);
setMinValue(newMinValue);
setMaxValue(newMaxValue);
};
// ...
return (
<>
<NumberInput value={minValue} onSubmit={onMinValueChanged} />
<NumberInput value={maxValue} onSubmit={onMaxValueChanged} />
</>
);
};
事情是:
当 newMaxValue
在 [2] 中调整(或 newMinValue
在 [3] 中)时,MinMaxNumberInputs
在其状态下保持正确的调整值,但这些值不会传播根据 NumberInput
,因此显示的值不是 updated/corrected.
我完全理解为什么这不起作用。 value
属性 仅在 [1] 处应用于 NumberInput
的内部状态一次,但之后不再应用。但是,我不知道如何在不“打破边界”的情况下克服这个问题 NumberInput
(例如,在那里也使用一些全局状态,...)。
非常感谢您提供这方面的指导!
谢谢
您的 NumberInput
是 UNCONTROLLED 组件,您的界面具有误导性,应该命名为 initialValue
而不是 value
.
因此你想要的是所谓的“混合组件”,在这种情况下,当你传递 value
属性时,它会变成 CONTROLLED:
export default function NumberInput(props: NumberInputProps) {
const [value, setValue] = useState(props.initialValue);
useEffect(() => {
setValue(props.value)
}, [props.value])
return <input value={value} />;
}
我有一个相当简单的 NumberInput
component/control 用 useState
处理它的内部状态(它的当前值)。 “外部世界”对此状态不感兴趣,但仅通过回调函数 onSubmit
接收更新,该回调函数在输入和模糊时调用。
我还有一个名为 MinMaxNumberInputs
的组件,它由 2 NumberInput
组成。这 2 个 NumberInput
彼此之间一无所知,父 MinMaxNumberInputs
必须处理一些“值同步”,例如确保 min <= max 等
这最后一部分是我有点卡住的地方,因为我不知道如何在需要时“强制设置”或从 MinMaxNumberInputs
覆盖 NumberInput
的内部状态.
可能最好通过代码解释:
NumberInput.tsx
// ...
type NumberInputProps = {
value: number;
onSubmit: (value: number) => void;
};
export default function NumberInput(props: NumberInputProps) {
// [1] props.value is obviously only applied on creation.
// Future changes have no effect.
const [value, setValue] = useState(props.value);
// Called on enter & blur
const submitValue = () => props.onSubmit(value);
// ...
return <input value={value} {/* ... */} />;
}
MinMaxNumberInputs.tsx
// ...
export const MinMaxValueInput = () => {
// Only for simpler showcasing, using global redux state in real world...
const [minValue, setMinValue] = useState(0);
const [maxValue, setMaxValue] = useState(0);
const onMinValueChanged = (newMinValue: number) => {
// [2] Ensure that entered value (min here) stays the same but adjust max if required
// ??? How to set adjusted value in max NumberInput ???
const newMaxValue = Math.max(newMinValue, maxValue);
setMinValue(newMinValue);
setMaxValue(newMaxValue);
};
const onMaxValueChanged = (newMaxValue: number) => {
// [3] Ensure that entered value (max here) stays the same but adjust min if required
// ??? How to set adjusted value in min NumberInput ???
const newMinValue = Math.min(minValue, newMaxValue);
setMinValue(newMinValue);
setMaxValue(newMaxValue);
};
// ...
return (
<>
<NumberInput value={minValue} onSubmit={onMinValueChanged} />
<NumberInput value={maxValue} onSubmit={onMaxValueChanged} />
</>
);
};
事情是:
当 newMaxValue
在 [2] 中调整(或 newMinValue
在 [3] 中)时,MinMaxNumberInputs
在其状态下保持正确的调整值,但这些值不会传播根据 NumberInput
,因此显示的值不是 updated/corrected.
我完全理解为什么这不起作用。 value
属性 仅在 [1] 处应用于 NumberInput
的内部状态一次,但之后不再应用。但是,我不知道如何在不“打破边界”的情况下克服这个问题 NumberInput
(例如,在那里也使用一些全局状态,...)。
非常感谢您提供这方面的指导!
谢谢
您的 NumberInput
是 UNCONTROLLED 组件,您的界面具有误导性,应该命名为 initialValue
而不是 value
.
因此你想要的是所谓的“混合组件”,在这种情况下,当你传递 value
属性时,它会变成 CONTROLLED:
export default function NumberInput(props: NumberInputProps) {
const [value, setValue] = useState(props.initialValue);
useEffect(() => {
setValue(props.value)
}, [props.value])
return <input value={value} />;
}