DrMeers
DrMeers

Reputation: 4207

How should I connect child components of a reduxForm to the redux state?

I have quite a complex multi-level deep/nested form connected to React/Redux using reduxForm(). As the form is very large, I've broken parts of it into child components. Some of these components require access to the Redux state, so need to either have connections passed down via props or be connect()ed. However when I use the normal Redux connect() function to connect the child components, it becomes impossible to edit the redux-form fields within them. So I tried using reduxForm() to connect the child components as well as the parent, which felt wrong, but appeared to work.

However I'm now discovering that some functionality like removeField() isn't working in the connected subcomponents -- e.g. child_form.removeField(index) removes all the child_forms, not just the one matching the index.

What is the correct/best-practice method of connecting child components of a reduxForm() component to the redux state? Passing everything through the hierarchy using props is going to become unwieldy very quickly...

Upvotes: 3

Views: 2477

Answers (1)

Florent
Florent

Reputation: 12420

However I'm now discovering that some functionality like removeField() isn't working in the connected subcomponents -- e.g. child_form.removeField(index) removes all the child_forms, not just the one matching the index.

There is two way to solve this:

  1. Use action creators

    The removeField method wraps the removeArrayValue action creator. You can dispatch this action to remove an entry of your form.

    // Removes the 4th row
    dispatch(removeArrayValue("myform", "myarrayfield", 3)) 
    
  2. Use a plugin

    Within the reducer plugin, you can intercept actions and trigger modifications of your form state. If you dispatch an action, you can intercept it and updates the field array.

Passing everything through the hierarchy using props is going to become unwieldy very quickly...

I've seen several workaround for this.

  1. Create multiple forms using the same form name. Internally Redux Form will merge them so your store contains the data of every sub form within the same object.

  2. Connect child form using connect and use action creators to manipulate the state.

  3. Break your form into smaller parts and pass fields. This is my favourite solution. We successfully do this in our application (on more than a hundred forms!).

    const MainForm = reduxForm({
      form: "main",
      fields: [
        SubForm1.fields,
        SubForm2.fields,
        SubForm3.fields,
      ]
    })(
      props => (
        <form onSubmit={props.handleSubmit}>
          <SubForm1 fields={props.fields} />
          <SubForm2 fields={props.fields} />
          <SubForm3 fields={props.fields} />
          <button type="submit">Send</button>
        </form>
      )
    )
    
    const SubForm1 = ({fields}) => (
      <div>
        <TextField {...fields.foo} />
        <TextField {...fields.bar} />
      </div>
    )
    
    SubForm1.fields = ["foo", "bar"]
    

Upvotes: 2

Related Questions