如何从外部覆盖内部组件状态



我有一个相当简单的NumberInput组件/控件,它使用useState处理其内部状态(当前值)。"外部世界"对这种状态不感兴趣,而只通过回调函数onSubmit接收更新,该函数在 Enter & blur 时调用。

我还有一个名为MinMaxNumberInputs的组件,它由 2NumberInput秒构建。这两个NumberInput彼此一无所知,父MinMaxNumberInputs必须处理一些"值同步",例如确保最小<=最大值等。

最后一部分是我有点卡住的地方,因为我不知道如何在需要时从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} {/* ... */} />;
}

最小最大数字输入.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} />
</>
);
};

问题是:

当在 [2] 中调整newMaxValue(或在 [3] 中调整newMinValue)时,MinMaxNumberInputs保持正确的调整值处于其状态,但这些值不会传播到相应的NumberInput,因此显示的值不会更新/更正。

我完全理解为什么这不起作用。value属性仅在 [1] 处应用于NumberInput的内部状态一次,之后不再应用。但是,我不知道如何在不"打破NumberInput边界"的情况下克服这个问题(例如,在那里也使用一些全局状态,......

我真的很感激这方面的一些指导!

谢谢

您的NumberInput不受控制的组件,您的界面具有误导性,应该将其命名为initialValue而不是value

因此,你想要的是所谓的"混合组件",在这种情况下,当你传递valueprop 时,它就会变成受控的

export default function NumberInput(props: NumberInputProps) {
const [value, setValue] = useState(props.initialValue);

useEffect(() => {
setValue(props.value)
}, [props.value])
return <input value={value}  />;
}

最新更新