首页 文章

ReactJS:在哪里将验证逻辑放在具有“嵌套”复合组件的表单中?

提问于
浏览
2

我是ReactJS的新手,并且不确定放置表单中嵌套子组件所需的验证逻辑的最佳位置,以及整个“父”表单组件本身 . 这是一个过于简化的例子,说明了我的问题......

我有一个这样的对象代表一个宠物主人:

{
  name: 'Jon Arbuckle',
  pets: [
   { name: 'Odie', type: 'dog' },
   { name: 'Garfield', type: 'cat' }
  ]
}

我正在使用名为 <PetOwnerForm> 的复合组件来渲染用于编辑此数据的表单 . <PetOwnerForm> 呈现如下内容:

<input type="text" value={name} />
<PetList value={petOwner.pets} />

<PetList> 是一个复合组件,它呈现:

<PetListItem value={this.props.value[i]} />  // Render this for each pet...
// buttons for adding/deleting pets

<PetListItem> 呈现如下内容:

<input type="text" value={this.props.value.name} />
<PetTypePicker value={this.props.value.type} />

最后, <PetTypePicker> 为宠物类型呈现 <select><option> .

<PetTypePicker> 需要知道如何验证所选类型,以便它可以显示内联错误消息(例如,确保选择了一个值) .

但是, <PetOwnerForm> 还需要知道如何验证宠物类型,因为它需要知道如何验证整个对象(在加载时,每次更新表单时,以及在将数据提交回服务器之前) . 如果任何字段无效,则应禁用"Save"按钮 .

那么,例如,“选择一个有效的宠物类型?”逻辑去? (请记住,这是一个简单的例子;实际上我有很多这样的字段和嵌套的复合组件) .

我到目前为止看到的选项是:

A)<PetOwnerForm><PetTypePicker> 中复制宠物类型(或任何字段)的验证逻辑 . 这可能只是在两个地方调用相同的共享验证函数:

//PetOwnerForm.js:
validate(petOwnerObj) {
  Util.isPetTypeValid(petOwnerObj.pets[i]) // for each pet
  // validate the other properties in petOwnerObj...
}

//PetTypePicker.js:  
validate(petType) {
  Util.isPetTypeValid(petType)
}

B) 使用具有自己的验证器的自定义PetOwner,Pet和PetType模型 . 这样,您始终可以要求模型自行验证,无论它在何处 . 也许这看起来像这样:

{
  name: { value: 'Jon Arbuckle', isValid: ()=>{...} },
  pets: [
  {
    name: { value: 'Garfield', isValid: ()=>{...} },
    type: { value: 'cat', isValid: ()=>{...} }
   },
   ...
  ]
}

C) 修改PetOwnerForm.js会递归宠物主人对象,验证每个值,并设置子组件可以引用的'errors'属性,从而产生如下对象:

{
  name: { value: 'Jon Arbuckle asdfasdfasdf^^', errors: ['Too many characters', 'Contains invalid character']] },
  pets: [
    {
      name: { value: '', errors: ['Required value missing'] },
      type: { value: 'tree', errors: ['Invalid pet type'] }
    },
    ...
  ]
}

Which option is recommended for React apps (or is there another option)?

1 回答

  • 1

    这是一个很精细的问题 . 此问题并非特定于ReactJS应用程序 . 它适用于遵循组件模型的所有框架 .

    以下是我的建议:

    • 区分动作驱动验证和数据格式验证 .

    • 低级组件知道它们接受的数据格式,因此必须对其进行验证 . 例如,邮政编码,电子邮件,电话,SSN等具有固定格式,其相应的组件必须验证正确的输入格式 .

    • 低级组件不知道正在对整个数据执行的操作 . 例如,宠物所有者类型的选择对于"create"宠物主人行动可以是强制性的,但对于"save draft"动作可以是可选的 . 因此,不了解最终操作的低级别组件不得执行操作驱动的验证 .

    • 动作驱动的验证必须由更高级别的组件识别操作来执行,例如PetOwnerForm . 必须将此类验证结果通知给低级组件,以便它们可以显示适当的错误 . 每个低级别组件都必须具有错误状态才能支持它 .

相关问题