javascript - 如何在 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"))
解决方案
发生这种情况是因为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]);
...
}
推荐阅读
- spring-boot - Spring数据R2DBC:org.springframework.data.mapping.PropertyReferenceException:没有找到类型的属性findAll
- sql - 连接不存在数据或链接不明显的表
- postgresql - 无法更新视图
- javascript - 正则表达式从开头和结尾提取所有匹配值
- jenkins - Jenkins 没有启动 Xvnc
- visual-studio-code - 更改未保存文件的文件夹位置
- html - 制作一个与前一个相同大小的文本框
- android - 执行 AndroidSchedulers.mainThread() 时出错
- sequelize.js - 从 Sequelize 中检索属性
- node.js - 如何在nodeJs中使函数同步