Search code examples
javascriptreactjsreduxreact-reduxredux-form

Simple Redux-Form Component returns undefined


Just created this form as part of a tutorial. However, my console log is giving me undefined whenever I submit the form. What am I doing wrong?

import React, {Component} from 'react';
import { reduxForm } from 'redux-form';

class Signin extends Component {
  handleFormSubmit({email, password}) {
    console.log(email); // this gives me 'undefined'
  }
  render() {
    const {handleSubmit, fields: {email, password}} = this.props;

    return (
    <form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
      <fieldset className="form-group">
      <label>Email:</label>
      <input {...email} className="form-control" />
      </fieldset>
      <fieldset className="form-group">
      <label>Password:</label>
      <input {...password} className="form-control" />
      </fieldset>
      <button action="submit" className="btn btn-primary">Sign in</button>
    </form>
    );
  }
}

export default reduxForm({
  form: 'signin',
  fields: ['email', 'password']
})(Signin);

Solution

  • This is due to an update to redux-form.

    Rather than importing the values of {email, password} from this.props we instead use a Field component imported from redux-form.

    import { Field, reduxForm } from 'redux-form';

    Then using it in place of the input tag you have:

    <fieldset className="form-group">
      <label>Email:</label>
      <Field
        name="email"
        className="form-control"
        component="input"
        type="text"
        placeholder="Email"
      />
    </fieldset>
    

    The connection of this input to redux-form now comes from the name property instead of extracting it from this.props

    Important to note: that the name MUST be the same as the name in the fields: [] array defined in the reduxForm:

    export default reduxForm({
      form: 'signin',
      fields: ['email', 'password']
    })(Signin);
    

    Building on this, if you want to customise the component that the Field uses, you can define your own custom component pretty easily.

    Instead of supplying a string to Field's component property, you can define a function:

    <div className="form-group">
      <label>Last name:</label>
      <Field type="text" className="form-control" placeholder="Smith" name="lastName"
      component={textField} />
    </div>
    

    textField is imported from another file: import {textField} from '../../redux_form_elements';

    And textField is as follows:

    import React from 'react';
    
    export const textField = (field) => (
      <div>
        <input className="form-control" {...field.input} type={field.type} placeholder={field.placeholder} />
        {field.meta.touched && field.meta.error &&
        <label id="basic-error" className="validation-error-label">This field is required.</label>
      }
      </div>
    );