Javascript reactjs-为什么表单值状态通过父道具和组件onChange更新?

Javascript reactjs-为什么表单值状态通过父道具和组件onChange更新?,javascript,forms,reactjs,Javascript,Forms,Reactjs,我正在阅读Fullstack React一书,在他们关于表单验证的示例中,他们创建了自己的字段组件(第204-212页),然后将字段值存储在字段状态和父状态中,这让我感到困惑。它们的字段组件有一个值属性以及一个包含值的状态。父组件需要知道每个字段值,这样它就可以作为一个整体进行表单验证,并且它还有一个包含值的状态 在字段内,它们通过在输入值更改时设置字段状态,以及在值属性更改时使用getDerivedStateFromProps来处理值更改: //(within Field) getDerive

我正在阅读Fullstack React一书,在他们关于表单验证的示例中,他们创建了自己的字段组件(第204-212页),然后将字段值存储在字段状态和父状态中,这让我感到困惑。它们的字段组件有一个
属性以及一个包含
的状态。父组件需要知道每个字段值,这样它就可以作为一个整体进行表单验证,并且它还有一个包含
的状态

在字段内,它们通过在输入值更改时设置字段状态,以及在值属性更改时使用getDerivedStateFromProps来处理值更改:

//(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 prop传递),将另一个方向上的值状态同步到父级:

这本书并没有真正解释为什么他们会复制这样的状态,只是说

“字段只需要两条数据,即当前数据 值和错误。与前面的章节一样,我们的表单组件 render()方法需要这些数据,我们的字段也需要这些数据 组成部分。”

而且

“一个关键区别是,我们的字段有一个父字段,有时是这样 父项将要更新字段的值属性。若要允许此操作, 我们需要创建一个新的生命周期方法, getDerivedStateFromProps()接受新值并更新 国家。”


我只是一个初学者,但在我看来,将
状态完全丢弃在字段中,并将其作为道具传入会更有意义。当输入发生更改时,使用字段调用onChange方法,并在该字段中调用父级的onInputChange。让onInputChange更新有关字段值的父状态,并将字段值作为道具传递给字段。现在这样做似乎有点多余,而且更容易出错。关于他们为什么这样做有什么见解吗?

还没有读过这本书,但在这里我将解释我为什么要写这样的代码

拥有这两种状态的要点是使
字段
组件更通用

在这种特定情况下,父级碰巧也将值保存在其状态中,
字段
组件通过从
getDerivedStateFromProps
上收到的
props
更新其状态,成为受控组件

然而,仍然有可能将
字段
组件用作非受控组件,那么
字段
的状态将是唯一的真相来源


在这两种情况下,只有一个真理来源,它维持React的做事方式,但是
字段
组件可以以受控和非受控的形式使用。

我完全同意你的看法。他们应该明确地提升国家地位,保持一个单一的真相来源。你一针见血,我能想到的在子组件中复制状态的唯一用例是,如果您试图以某种方式保留原始状态。我能看到的唯一原因是,如果示例继续,您必须在此基础上构建,将子组件和父组件之间的状态解耦是有意义的。即便如此,它也可能导致混乱的反应体系结构。我将分享我的两分钱,即使到今天我还没有读过一本好的React教程,甚至没有参加过一次写得很好的React评估测试。我的React技能来自React和Redux站点本身的例子。@JonasW。谢谢:)但有趣的家伙们,我想我会看看以后的做法是否有意义。@josephnvu到目前为止我喜欢这本书,所以希望它以后有意义,或者它只是一个令人困惑的例子:TAh,好的。这很有道理。他们之前讨论过如何将输入表单从非受控(使用ref)转换为受控组件,以及如何不真正推荐非受控组件。但我猜他们这样做是为了让它仍然可以不受控制地工作。
//(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});
};