简体   繁体   English

React:根据动态生成的表单中的其他字段更新字段值

[英]React: update a field value based on another field in dynamically generated form

I'm trying to find out the "proper" way to do the following in React: 我试图找出在React中执行以下操作的“正确”方法:

  • I have a form with two fields, url and title . 我有一个包含两个字段的表单, urltitle
  • Whenever url 's value changes, I make an API call to Embedly to retrieve metadata about the link. 每当url的值发生变化时,我都会对Embedly进行API调用,以检索有关链接的元数据。
  • Once the metadata has been retrieved, I want to update the title field with the result. 一旦检索到元数据,我想用结果更新title字段。

The difficulty here is that the url and title fields are not in the same component. 这里的困难是urltitle字段不在同一个组件中。 Here's the basic structure of the form (I'm using Formsy ): 这是表单的基本结构(我使用的是Formsy ):

<Formsy.Form onSubmit={this.submitForm} onChange={this.updateState} ref="form">
  {fields.map(field => <FormComponent 
    name={field.name}
    type={field.type}
    value={field.value}
  />)}
  <Button type="submit">Submit</Button>
</Formsy.Form>

As you can see, the form loops over an array of fields and calls a generic <FormComponent/> component for each of them, which is basically a big switch that then calls the appropriate Formsy Component based on the field's type . 正如您所看到的,表单循环遍历一个字段数组并为每个字段调用一个通用的<FormComponent/>组件,这基本上是一个大的switch ,然后根据字段的type调用相应的Formsy组件

The logic for querying Embedly is already working inside the component for the url field, but I'm not sure if there's a way to accomplish what I want while still using the default Input component for title ? 查询Embedly的逻辑已经在url字段的组件内部工作,但我不确定是否有办法在仍然使用title的默认Input组件时完成我想要的内容?

[Edit: thanks to Dan I was able to come up with a better solution for step 4 and after] [编辑:感谢Dan,我能够为第4步及之后提出更好的解决方案]

So here's the solution I came up with. 所以这是我提出的解决方案。 I have no clue if it's the best pattern or not, but at least so far it seems to work. 我不知道它是否是最好的模式,但至少到目前为止似乎有效。

Step 1 : add a addToPrefilledValues method to the <Form/> component that takes a property and adds it to the prefilledValues object on that component's state. 步骤1 :向<Form/>组件添加addToPrefilledValues方法,该组件接受属性并将其添加到该组件状态的prefilledValues对象。

Step 2 : add addToPrefilledValues to the form component's context so that the method is passed on to all child components (note: I could also pass it as a prop but context seems easier to pass it on to grandchild components). 第2步 :将addToPrefilledValues添加到表单组件的context以便将该方法传递给所有子组件(注意:我也可以将其作为prop传递,但上下文似乎更容易将其传递给孙组件)。

Step 3 : make my <URLField/> component call addToPrefilledValues whenever it receives new metadata from Embedly: 第3步 :让我<URLField/>部件呼叫addToPrefilledValues每当它接收到来自Embedly新的元数据:

this.context.addToPrefilledValues({title: result.title, body: result.description});

Step 4 [Wrong, see below] : in the <TitleField/> component's shouldComponentUpdate method, watch for changes to the context and update the field's value (if it's empty): 第4步 [错误,见下文] :在<TitleField/>组件的shouldComponentUpdate方法中,监视上下文的更改并更新字段的值(如果它为空):

shouldComponentUpdate(nextProps, nextState, nextContext) {

  const nextTitle = nextContext.prefilledValues && nextContext.prefilledValues.title;
  const currentTitle = this.context.prefilledValues && this.context.prefilledValues.title;

  if (!!nextTitle && nextTitle != currentTitle && !this.input.getValue()) {
    this.input.setValue(nextTitle);
  }

  return true;
}

Step 4 (better) : whenever the form changes, store all of the form's values in a currentValue object on the form's state. 第4步(更好) :每当表单更改时,将所有表单的值存储在表单状态的currentValue对象中。

Step 5 : Look at: 第5步 :看看:

  1. the original value of the field (ie in the database), as passed through this.props ). 字段的原始值(即在数据库中),通过this.props传递。
  2. the current value being typed in the field, as found in this.state.currentValue . 在字段中键入的当前值,如this.state.currentValue
  3. the prefilled value generated by the Embedly API call, as found in this.state.prefilledValue . 由Embedly API调用生成的预填充值,如this.state.prefilledValue

Figure out which one is correct (ie if the user hasn't entered anything in the field prefill it, if not don't) and pass that on to the form field child component. 弄清楚哪一个是正确的(即,如果用户没有在字段中输入任何内容,则预填充它,如果不是)并将其传递给表单字段子组件。

This achieves the desired result: 这实现了预期的结果:

  • <URLField/> and <TitleField/> don't have to know about or communicate with each other. <URLField/><TitleField/>不必彼此了解或通信。
  • <Form/> doesn't have to know about <URLField/> or <TitleField/> either. <Form/>也不必了解<URLField/><TitleField/>

As @ffxsam suggested though, I should probably just use Redux Form… 正如@ffxsam建议的那样,我应该只使用Redux Form ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM