【发布时间】:2018-10-29 02:25:03
【问题描述】:
我正在阅读 Fullstack React 书籍,在他们关于表单验证的示例中,他们创建了自己的 Field 组件(第 204 - 212 页),然后将字段值存储在 Field 状态和父状态中,这让我很困惑。他们的 Field 组件有一个value 属性以及一个包含value 的状态。父组件需要知道每个字段的值,这样它才能整体做表单验证,所以它也有一个包含value的状态。
在 Field 中,它们通过在输入 value 更改时设置 Field 状态以及在 value 属性更改时使用 getDerivedStateFromProps 来处理 value 更改:
//(within Field)
getDerivedStateFromProps(nextProps) {
return {value: nextProps.value}
}
onChange = evt => {
const name = this.props.name;
const value = evt.target.value;
const error = this.props.validate ? this.props.validate(value) : false;
this.setState({value, error});
this.props.onChange({name, value, error});
};
它们还通过调用父级的 onInputChange 函数(作为 onChange 属性传递)将另一个方向的值状态同步到父级:
//(within parent component)
onInputChange = ({name, value, error}) => {
const fields = Object.assign({}, this.state.fields);
const fieldErrors = Object.assign({}, this.state.fieldErrors);
fields[name] = value;
fieldErrors[name] = error;
this.setState({fields, fieldErrors});
};
这本书并没有真正解释他们为什么像这样复制状态,只是说,
"Field 只需要两条数据,当前 价值和错误。就像前面的部分一样,我们的表单组件 它的 render() 方法需要这些数据,我们的 Field 也是如此 组件。”
还有
“一个关键的区别是我们的 Field 有一个父级,有时这 parent 会想要更新我们的 Field 的 value 属性。为了允许这一点, 我们需要创建一个新的生命周期方法, getDerivedStateFromProps() 接受新值并更新 状态。”
我只是一个初学者,但在我看来,在 Field 中完全放弃 value 状态并将其作为道具传入会更有意义。当输入发生变化时,使用 Field 调用 onChange 方法,并在其中调用父级的 onInputChange。让 onInputChange 更新有关字段值的父状态,并将字段值作为道具传递给字段。现在完成的方式似乎有点多余并且更容易出错。任何关于他们为什么这样做的见解?
【问题讨论】:
-
我完全同意你的看法。他们应该明确地提升状态并保持单一的事实来源。
-
你一针见血,我能想到的在子组件中复制状态的唯一用例是,如果你试图以某种方式保留原始状态。
-
唯一的原因是我可以看到这个例子是否继续下去,你必须在此基础上构建,在此基础上解耦子级和父级之间的状态是有意义的。即便如此,它也可能会导致一条混乱的 React 架构之路。我将分享我的两分钱,即使直到今天我还没有阅读过好的 React 教程,甚至没有参加过写得很好的 React 评估测试。我的 React 技能都来自 React 和 Redux 站点本身的示例。
-
@JonasW。谢谢 :) 但是有趣的家伙,我想我以后会看看这样做是否有意义。
-
@josephnvu 到目前为止我很喜欢这本书,所以希望以后它会有意义,或者这只是一个令人困惑的例子:T
标签: javascript forms reactjs