10

I'm having an issue getting my signin form field validation to work with redux-form. For the moment, I'm just trying to get sync validation to work so I can check for basic errors. The problem is that the form appears to only check validation when the component mounts, then not again after that point. Here's the code I have:

import React from 'react';
import { Field, reduxForm } from 'redux-form';
import * as Redux from 'react-redux';

import Input from './../../helpers/Input';
import Button from './../../helpers/Button';

export const Signup = React.createClass({

    renderInput({ label, type, input: { value }, meta: { touched, error }}){
        return (
            <Input label={ label }
                   type={ type }
                   filled={ value ? true : false }
                   touched={ touched }
                   error={ error } />
        );
    },

    render(){

        const { handleSubmit } = this.props;

        return(
            <div>
                <form onSubmit={ handleSubmit }>
                    <Field name="email" label="Email" component={ this.renderInput } />
                    <Field name="username" label="Username" component={ this.renderInput } />
                    <Field name="password" label="Password" type="password" component={ this.renderInput } />
                    <Field name="confirmPassword" label="Confirm Password" type="password" component={ this.renderInput } />
                    <Button type="submit" btnType="main" btnIcon="" btnText="Create Account" />
                </form>
            </div>
        );
    }
});

export const validate = values => {
    const errors = {};
      if (!values.username) {
          errors.username = 'Required';
      } else if (values.username.length > 15) {
          errors.username = 'Must be 15 characters or less';
      }

      if (!values.email) {
          errors.email = 'Required';
      } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
          errors.email = 'Invalid email address';
      }
      console.log(errors);
      return errors;
};

export default reduxForm({
  form: 'signup',
  validate
})(Signup);

I sense that I'm missing something very fundamental here, but I'm stumped. I feel like an action should be dispatched to toggle the "touched" property onBlur (and thereby rerendering the form), but it doesn't seem to be doing that and I couldn't find anything like that reading through the redux-form docs. Any ideas?

1 Answer 1

4
+50

You're not passing onChange handler to your Input component, so redux-form doesn't know that values have changed.


The problem is here:

renderInput({ label, type, input: { value }, meta: { touched, error }}){
    return (
        <Input label={ label }
               type={ type }
               filled={ value ? true : false }
               touched={ touched }
               error={ error } />
    );
},

To fix that, pass the input as a property to your Input component and have it defined like that for example:

<div className="input-row">
  <input {...input} type="text"/>
  {touched && error && 
  <span className="error">{error}</span>}
</div>

Don't forget to change the function signature to renderInput({ label, type, input, meta: { touched, error }}) { ... } - value is removed here.


As an alternative, you could explicitly pass onChange:

 renderInput({ label, type, input: { value, onChange }, meta: { touched, error }}){
        return (
            <Input label={ label }
                   onChange = { onChange }
                   type={ type }
                   filled={ value ? true : false }
                   touched={ touched }
                   error={ error } />
        );
    },

And then use onChange in your <Input ... />

Sign up to request clarification or add additional context in comments.

1 Comment

I wish I could upvote this a 100 times. Been googling for an hour.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.