reactjsreduxredux-formreact-redux-form

How to reset form on submission with Redux Form?


I'm creating a basic portfolio website, that has a Contact form section, where people can send me a message to my email via Formspree. I'm using Redux Forms for this and the form works, but I'd like to reset the form fields and add some kind of 'success' message on successful submit.

I've tried 2 methods: 1) calling this.props.resetForm() and 2) calling dispatch(reset('ContactForm'). Neither have worked.

Here is the code:

contact.js:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Field, reduxForm } from 'redux-form';
import { sendMail } from '../actions';


class Contact extends Component {
  renderField(field) {
    const { meta: { touched, error } } = field;
    const className = `form-group ${touched && error && 'has-error'}`;

    return (
      <div className={className}>
        <label>{field.label}</label>
        {field.type == 'text' ?
        <input
          className='form-control'
          type={field.type}
          {...field.input}
        /> :
        <textarea
          className='form-control'
          rows='5'
          {...field.input}
        />}
        <div className='help-block'>
          {touched && error}
        </div>
      </div>
    );
  }

  onSubmit(values) {
    this.props.sendMail(values, () => {
      this.props.resetForm();
    });
  }


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

    return (
      <div id='contact'>
        <h1>Contact</h1>
        <p>Feel free to drop me a mail. Whether it's work-related or about coding, tech, entrepreneurship, travel, football or life in general. I'm always looking to connect with other people.</p>
        <div id='contact-form'>
          <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
            <Field
              label='Name:'
              name='name'
              type='text'
              component={this.renderField}
            />
            <Field
              label='Email:'
              name='email'
              type='text'
              component={this.renderField}
            />
            <Field
              label='Message:'
              name='message'
              type='textarea'
              component={this.renderField}
            />
            <button
              type='submit'
              className='btn btn-primary'
            >
              Submit
            </button>
          </form>

        </div>
      </div>
    );
  }
}

function validate(values) {
  const errors = {};

  if (!values.name) {
    errors.name = "Enter a name"
  }

  if (!values.email) {
    errors.email = "Enter an email"
  }

  if (!values.message) {
    errors.message = "Enter a message"
  }
  return errors;
}

export default reduxForm({
  form: 'ContactForm',
  validate
})(
  connect(null, { sendMail })(Contact)
);

actions/index.js:

import axios from 'axios';
import { reset } from 'redux-form';

export const MAIL_SENT = 'MAIL_SENT';

const ROOT_URL='https://formspree.io/'
const EMAIL = 'xxxxxx@gmail.com'

export function sendMail(values) {
  const request = axios.post(`${ROOT_URL}${EMAIL}`, values);

  return {
    type: MAIL_SENT,
    payload: true
  };
  dispatch(reset('ContactForm'));
}

Solution

    1. You need to add a constructor to the class contact.

      class Contact extends Component {
        constructor(props) {
          super(props);
        }
        ...
      };
      
    2. Putting dispatch(reset('ContactForm')) after return syntax, it would never get called. By the way, the action creator is supposed to be a pure function. Adding dispatch action to it is not a good idea.

    Hope this help.