Redux-form FieldArray, handleSubmit 'undefined

I am working to use fieldquray redux form. I am having problems connecting the form to the actual react component. When I try to submit the form, I get the following error:error 'handleSubmit' is not defined

File below ... Am I building this form correctly in my component? Any idea why handleSubmit is a bug? Thanks to

import React from 'react';
import {Field, FieldArray, reduxForm} from 'redux-form'
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as inviteActions from '../../actions/inviteActions';

let renderEmailField = ({input, label, type, meta: {touched, error}}) =>
  <div>
    <label>{label}</label>
    <div>
      <input {...input} name="email" type="email"/>
      {touched && error && <span>{error}</span>}
    </div>
  </div>

let renderEmails = ({fields, meta: {submitFailed, error}}) =>
  <ul>
    <li>
      <button type="button" onClick={() => fields.push()}>Add Email</button>
    </li>
    {fields.map((email, index) =>
      <li key={index}>
        {index > 2 && <button
          type="button"
          title="Remove Email"
          onClick={() => fields.remove(index)}
        />}
        <Field
          name={email}
          component={renderEmailField}
          label={`Email #${index + 1}`}
        />
      </li>
    )}
    {submitFailed && error && <li className="error">{error}</li>}
  </ul>

let EmailsForm = ({handleSubmit, pristine, reset, submitting}) =>
  <form onSubmit={handleSubmit}>
    <FieldArray name="emails" component={renderEmails} />
    <div>
      <button type="submit" disabled={submitting}>Submit</button>
      <button type="button" disabled={pristine || submitting} onClick={reset}>
        Clear Values
      </button>
    </div>
  </form>


class InvitePage extends React.Component {

  handleSubmit(data) {
    console.log(data)
    this.props.actions.createInvites(data);
  }

  render() {

    return (
      <div>
        <h1>Invites</h1>
        <EmailsForm onSubmit={handleSubmit}/>
      </div>
    );
  }

}

EmailsForm = reduxForm({
  form: 'emailsForm',
  initialValues: {
    emails: ['', '', '']
  },
  validate(values) {
    const errors = {}
    if (!values.emails || !values.emails.length) {
      errors.emails = {_error: 'At least one email must be entered'}
    }
    else {
      let emailsArrayErrors = []
      values.emails.forEach((email, emailIndex) => {
        const emailErrors = {}
        if (email == null || !email.trim()) {
          emailsArrayErrors[emailIndex] = 'Required'
        }
      })
      if (emailsArrayErrors.length) {
        errors.emails = emailsArrayErrors
      }
    }
    return errors
  }
})(EmailsForm)

const mapStateToProps = state => {
  return {
    currentUser: state.currentUser
  };
};

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(inviteActions, dispatch)
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(InvitePage);

      

+3


source to share


2 answers


You have not provided an onSubmit function as an alert to the EmailsForm. You can pass it in two ways:

EmailsForm = reduxForm({
  form: 'emailsForm',
  ...
  onSubmit: () => {}
  ... 
})(EmailsForm)

      

or you can pass onSubmit

as a prop when callingEmailsForm

<EmailsForm onSubmit={() => {}} />

      

In your case, you need to write like this:

<EmailsForm onSubmit={this.handleSubmit.bind(this)}/>

      



In my opinion, if you can reuse these small components renderEmailField, renderEmails, EmailsForm

, then you can create them as a separate component, as you have done now.

I would recommend that you should not separate the EmailsForm from the InvitePage class as you will have to transfer all the details from the InvitePage site to the EmailsForm as your requirement grows. The InvitePage function does not serve any other purpose at this time than passing on the onSubmit function.

class InvitePage extends React.Component {

  handleSubmit = data => {
    console.log(data)
    this.props.actions.createInvites(data);
  }

  render() {
    const { pristine, reset, submitting } = this.props
    return (
      <div>
        <h1>Invites</h1>
        <form onSubmit={this.handleSubmit}> // react recommends we should not bind function here. Either bind that in constructor or write handleSubmit like I have written.
          <FieldArray name="emails" component={renderEmails} />

          <div>
            <button type="submit" disabled={submitting}>Submit</button>
            <button type="button" disabled={pristine || submitting} onClick={reset}>
              Clear Values
            </button>
          </div>
        </form>
      </div>
    )
  }

}

InvitePage = reduxForm({
  form: 'emailsForm',
  initialValues: {
    emails: ['', '', ''],
  },
  validate(values) {
    ...
  }
})(InvitePage)

      

Hope it works.

Try using const rather than let if you are not modifying the value of any variable.

+3


source


You must explicitly pass a callback function to handleSubmit like this.

render() {
    const { handleSubmit } = this.props;


    return (
      <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
          <Field name="firstName" component={this.renderField} type="text" className="curvedBorder" label="First Name" />
          ...
          <button type="submit" className="btn btn-primary">Submit</button>
      </form>
    );
}


onSubmit(values) {
    // handle form submission here.
    console.log(values);
}

      



Hope this helps. Happy coding!

+2


source







All Articles