Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

redux-form fields not rerendering/updating after form loads

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?

like image 383
Nate Kimball Avatar asked Sep 11 '16 01:09

Nate Kimball


1 Answers

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 ... />

like image 147
Lyubomir Avatar answered Sep 19 '22 02:09

Lyubomir