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