Eric Stermer
Eric Stermer

Reputation: 1101

redux-form v6: Form submission canceled because the form is not connected

I am getting this error in my console.

"Form submission canceled because the form is not connected"

after trying to migrate my redux-form from v5 to v6 since we migrated our app to a more recent version of React.

I am not sure what is going wrong here so i figured I could use a second or third pair of eyes.

Here is my "Smart Component"

import React, { PropTypes } from 'react';
import { reduxForm } from 'redux-form/immutable';
import { connect } from 'react-redux';
import { logUserIn } from '../../actions/authentication';
import { VALID_EMAIL_REGEX } from '../../config/app_config';
import LoginForm from './LoginForm';

const FORM_ID = 'loginForm';

export class LoginFormContainer extends React.Component {

  static propTypes = {
    handleSubmit: PropTypes.func.isRequired,
    submitting: PropTypes.bool.isRequired,
    loginAction: PropTypes.func.isRequired,
  };

  performLogin = (params) => {
    const { loginAction } = this.props;
    const credentials = {
      email: params.email,
      password: params.password,
    };
    loginAction(credentials, '/home');
  }

  render() {
    const { handleSubmit, submitting } = this.props;
    return (
      <LoginForm
        handleSubmit={ handleSubmit }
        loginFunction={ this.performLogin }
        submitting={ submitting }
      />
    );
  }
}

const validate = values => {
  const errors = {};
  if (!values.email || values.email === '') {
    errors.email = 'Required';
  }
  else if (!VALID_EMAIL_REGEX.test(values.email)) {
    errors.email = 'Invalid email address';
  }
  if (!values.password || values.password === '') {
    errors.password = 'Required';
  }
  return errors;
};

LoginFormContainer = reduxForm({
  form: FORM_ID,
  validate,
})(LoginFormContainer);

export default connect(null, {
  loginAction: logUserIn,
})(LoginFormContainer);

I am passing down my submission handler function as a prop to my actual form that contains the Field component for inputs. The loginAction will link to the action for redux to send the values to the backend and redirect to home.

import React, { PropTypes } from 'react';
import { Field } from 'redux-form/immutable';
import { getClassName, checkButtonDisabled } from '../../utils/forms';
import { Link } from 'react-router';

const renderInput = (field) => {
  return (
    <div className={ getClassName(field.meta.touched, field.meta.error) }>
      <input
        {...field.input}
        className="form-control form-control-success"
        type={field.type}
      />
      {field.meta.touched &&
       field.meta.error &&
       <span className="error">{field.meta.error}</span>}
    </div>
  );
};

export default class LoginForm extends React.Component {

  static propTypes = {
    handleSubmit: PropTypes.func.isRequired,
    loginFunction: PropTypes.func.isRequired,
    submitting: PropTypes.bool.isRequired,
  };

  render() {
    const {
      loginFunction,
      submitting } = this.props;

    return (
      <form onSubmit={ loginFunction.bind(this) }>
        <fieldset>
          <div>
            <label className="form-control-label">
              Email address&nbsp;
            </label>
            <Field
              name="email"
              component={renderInput}
              type="text"
              placeholder="[email protected]"
            />
          </div>

          <div>
            <label className="form-control-label">
              Password&nbsp;
            </label>
            <Field
              name="password"
              component={renderInput}
              type="password"
              placeholder="your password"
            />
          </div>

        </fieldset>
        <button
          type="submit"
          className="btn btn-primary"
          disabled={ checkButtonDisabled(submitting) }
        >
          Log In
        </button>&nbsp;
        <Link to="/forgot-password">Forgot Password?</Link>
      </form>
    );
  }
}

I successfully was able to get the form to work but when I hit login I get the error above and I am redirected to home, but I am not authenticated and I get a 422 error as well. I couldn't tell if my form connecting is the only error or if my action is not getting the right information from the form submission function.

Got any suggestions?

Upvotes: 3

Views: 6149

Answers (2)

Deividas
Deividas

Reputation: 6507

You are redirected home, because your loginFunction() is fired, but the form is not submitted

There are a couple of things that need to be updated. Your <form> tag must have a corresponding id and it should handle submit by passing your function to redux-form inbuilt submit handler. So you modifying LoginForm class as follows should get the form working

<form id="loginForm" onSubmit={  handleSubmit(this.loginFunction.bind(this)) } >

More about internal redux-form method handleSubmit here: http://redux-form.com/6.5.0/docs/api/Form.md/

Upvotes: 2

Eric Stermer
Eric Stermer

Reputation: 1101

Using the answer given to me above I just wanted to clarify what I did to solve the issue.

I grabbed the handleSubmit method that comes from the reduxForm and passed it to the LoginForm as a prop from the container that also retrieved it from the props.

I also imported the Form component from redux-form on the LoginForm component and just simply replaced the normal JSX tag with .

here were the final changes I made.

LoginForm.jsx:

//Added Form from redux-form
import { Field, Form } from 'redux-form/immutable';
    render() {
        const {
          handleSubmit,//defined handleSubmit function from props which comes from the reduxForm being exported to the state.
          loginFunction,
          submitting } = this.props;

        return (
          //replaced <form></form> with <Form></Form>
          <Form id="loginForm" onSubmit={ handleSubmit(loginFunction.bind(this)) }>
          //passed my loginFunction into the handleSubmit function
          //added an id to <Form> that corresponds to the forms id that was passed in reduxForm({ form: 'loginForm' })
            <fieldset>
              <div>
                <label className="form-control-label">
                  Email address&nbsp;
                </label>
                <Field
                  name="email"
                  component={renderInput}
                  type="text"
                  placeholder="[email protected]"
                />
              </div>

              <div>
                <label className="form-control-label">
                  Password&nbsp;
                </label>
                <Field
                  name="password"
                  component={renderInput}
                  type="password"
                  placeholder="your password"
                />
              </div>

            </fieldset>
            <button
              type="submit"
              className="btn btn-primary"
              disabled={ checkButtonDisabled(submitting) }
            >
              Log In
            </button>&nbsp;
            <Link to="/forgot-password">Forgot Password?</Link>
          </Form>
        );

Upvotes: 0

Related Questions