首页 > 解决方案 > 如何在 React 中从头开始创建受控输入

问题描述

本质上,我想让 Parent 元素控制其子元素的值。通过之前使用 React 输入,我知道您需要传递一个 onChange 道具,以便 Parent 可以更新它传递给其子级的值。

我已将 value 和 onChange props 设为可选,因为我还想支持您将 Child 用作不受控制的输入的情况。

Child 的不受控制和未处理的受控变体都有效。然而,处理的受控变体没有。

任何想法如何让它发挥作用?我已将下面的 JSFiddle 与显示我的问题的最小示例链接起来:

https://jsfiddle.net/numberjak/wufdh0ys/3/

代码:

const Parent = () => {
    const [parentValue, setParentValue] = React.useState(0);

  return (
    <div>
      Should act like uncontrolled input (i.e. value should change) [WORKS]
      <Child />
      Should act like controlled input (i.e. value should change because onChange handler passed in) [DOESN'T WORK]
      <Child value={parentValue} onChange={setParentValue} />
      Should act like controlled input, except no onChange handler means value shouldn't change [WORKS]
      <Child value={5} />
    </div>
  );
};

const Child = ({value, onChange}) => {
    const [childValue, setChildValue] = React.useState(value !== undefined ? value : 0);

  const handleOnChange = (newValue) => {
    if (value === undefined) {
        setChildValue(newValue);
    }

    if (onChange !== undefined) {
        onChange(newValue);
    }
  };

  return (
    <GrandChild value={childValue} onChange={handleOnChange} />
  );
};

const GrandChild = ({value, onChange}) => {
    const handleOnClick = () => {
    onChange(value + 1);
  };

  return (
    <div className="grand-child" onClick={handleOnClick}>{value}</div>
  );
};

ReactDOM.render(<Parent />, document.querySelector("#app"))

标签: javascriptreactjsreact-hooksjsx

解决方案


发生这种情况是因为value您传递给Child组件的道具仅用作useState钩子的初始值。在下一次更新useState时将忽略此值,因为childValue已经初始化。childValue要更新您需要使用的状态变量useEffect,您必须调用setChildValue

const Child = ({value, onChange}) => {
  const [childValue, setChildValue] = React.useState(value !== undefined ? value : 0);

  React.useEffect(() => {
    value !== undefined && setChildValue(value);
  }, [value]);

...
}

推荐阅读