Search code examples
redux-form

How do I make a reusable form component group with Redux-Form v6?


I'm trying to make a reusable form component group (section?) for use with Redux-Form v6. Ideally I don't want it to be aware of where it is used within a form, so that I can use it anywhere within a form (at the root or nested). How can I do this?

For example, I have an Address component that uses Redux-Form's Field for address1, city, state, zip, etc, like this:

class Address extends React.Component {
  render() {
    return (
      <Field
        component={MyReduxFormInput}
        name="address1" // <== How to name for generic case?
      />
    )
  }
}

Here's a simplified MyReduxFormInput:

module.exports = field => {
  return <input {...field.input} />
}

I'm creating a form where I need to collect the user's address, as well as multiple addresses from some professional references. So, I want to use Address once at the root and multiple times in a nested fashion. The trick is, I can't simply use Address as I've written it above, because while that will work for the root address, it won't work for nested situations. As shown in the FieldArray example docs, the name supplied to Field needs to be name={`${member}.address1`}. But then that wouldn't work at the root.

One idea which just occurred to me is for the Address component to take a member argument, which would be blank at the root. I'll try that and report back. But I was thinking Redux-Form Field components would be automatically aware of their nesting level; they should look up their hierarchy and be able to know their necessary name prefix.


Solution

  • My idea of my component taking a member prop (as in, a name prefix depending on the nesting) works great. Wish I would've thought of it many hours ago.

    Here's what Address looks like:

    class Address extends React.Component {
      static propTypes = {
        member: PropTypes.string
      }
    
      static defaultProps = {
        member: ''
      }
    
      render() {
        const { member } = this.props
        const name = n => `${member}${n}`
    
        return (
          <Field
            component={MyReduxFormInput}
            name={name('address1')}
          />
        )
      }
    }
    

    And here's how it might be used:

    const references = ({ fields }) => {
      return (
        <div>
          fields.map((member, index) => {
            return <Address member={member} key={index} />
          })
        </div>
      )
    }
    
    <Address />
    <FieldArray name="professionalReferences" component={references} />