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

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 (例如,在那里也使用一些全局状态,...)。

非常感谢您提供这方面的指导!

谢谢

您的 NumberInputUNCONTROLLED 组件,您的界面具有误导性,应该命名为 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}  />;
}