Victor
Victor

Reputation: 762

React Redux Form: form is submiting with old values

I have a FieldArray in Redux Form that I push objects inside this array and right after that I have a callback to trigger a function to make a POST request.

When I submit the form I get the old values, because the push() method of the Redux Form is an async dispach from redux.

// Parent component
<FieldArray
     name="myObjects"
     component={ChildComponent}
     onSubmitObjects={this.onSubmit} />

// Function
onSubmit = async () => {
    const { getFormValues } = this.props;

    const data = {
        myObjects: getFormValues.myObjects
    }

    try {
        // const contact = await Service.updateUser(data);

    } catch (e) {
        console.log(e)
    }
}

I need to submit the form with the new values added in the array right after the push method.

// Function inside ChildComponent
addNewObject = () => {
        const { fields, onSubmitObjects} = this.props;

        fields.push({
            number: 1,
            name: 'Foo',
        });

        if (onSubmitObjects) {
            onSubmitObjects(); // cb() to trigger a function in the parent component
        }
    }

Is there a way to call the callback with the new values right after the push method?

Upvotes: 3

Views: 1313

Answers (1)

Tiago Alves
Tiago Alves

Reputation: 2316

You should use a form with redux-form handleSubmit to wrap your FieldArray. You can optionally pass your custom submit function (to make API requests, submit validation, etc.) to handleSubmit so it'd look like this <form onSubmit={handleSubmit(this.onSubmit)}> ...

See this example from redux-form official docs:

FieldArraysForm.js

import React from 'react'
import {Field, FieldArray, reduxForm} from 'redux-form'
import validate from './validate'

const renderField = ({input, label, type, meta: {touched, error}}) => (
  <div>
    <label>{label}</label>
    <div>
      <input {...input} type={type} placeholder={label} />
      {touched && error && <span>{error}</span>}
    </div>
  </div>
)

const renderHobbies = ({fields, meta: {error}}) => (
  <ul>
    <li>
      <button type="button" onClick={() => fields.push()}>Add Hobby</button>
    </li>
    {fields.map((hobby, index) => (
      <li key={index}>
        <button
          type="button"
          title="Remove Hobby"
          onClick={() => fields.remove(index)}
        />
        <Field
          name={hobby}
          type="text"
          component={renderField}
          label={`Hobby #${index + 1}`}
        />
      </li>
    ))}
    {error && <li className="error">{error}</li>}
  </ul>
)

const renderMembers = ({fields, meta: {error, submitFailed}}) => (
  <ul>
    <li>
      <button type="button" onClick={() => fields.push({})}>Add Member</button>
      {submitFailed && error && <span>{error}</span>}
    </li>
    {fields.map((member, index) => (
      <li key={index}>
        <button
          type="button"
          title="Remove Member"
          onClick={() => fields.remove(index)}
        />
        <h4>Member #{index + 1}</h4>
        <Field
          name={`${member}.firstName`}
          type="text"
          component={renderField}
          label="First Name"
        />
        <Field
          name={`${member}.lastName`}
          type="text"
          component={renderField}
          label="Last Name"
        />
        <FieldArray name={`${member}.hobbies`} component={renderHobbies} />
      </li>
    ))}
  </ul>
)

const FieldArraysForm = props => {
  const {handleSubmit, pristine, reset, submitting} = props
  return (
    <form onSubmit={handleSubmit}>
      <Field
        name="clubName"
        type="text"
        component={renderField}
        label="Club Name"
      />
      <FieldArray name="members" component={renderMembers} />
      <div>
        <button type="submit" disabled={submitting}>Submit</button>
        <button type="button" disabled={pristine || submitting} onClick={reset}>
          Clear Values
        </button>
      </div>
    </form>
  )
}

export default reduxForm({
  form: 'fieldArrays', // a unique identifier for this form
})(FieldArraysForm)

Upvotes: 1

Related Questions