Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redux Form: Input stays with 'touched: false'

Wanted to validate my inputs and change the CSS depending of the user interaction.

Starting with a required validation method I wrap all my inputs component with a <Field> and pass to validate an array of func. Just required for now.

But for all my fields the value stay the same touched: false and error: "Required". If I touch or add stuff in the input, those values stay the same.

Validation

export const required = value => (value ? undefined : 'Required')

NameInput

import React from 'react';
import { Field } from 'redux-form'
import InputItem from 'Components/InputsUtils/InputItem';
import { required } from 'Components/InputsUtils/Validation';

const NameInput = () => (
  <Field
    name={item.spec.inputName}
    type={item.spec.type}
    component={InputItem}
    validate={[required]}
    props={item}
  />
);

export default NameInput;

InputItem

import React from 'react';

const InputItem = ({ spec, meta: { touched, error } }) => {        
  const { type, placeholder } = spec;
  return (
    <input
      className="input"
      type={type}
      placeholder={placeholder}
    />
  );
};

export default InputItem;
like image 438
Ragnar Avatar asked Mar 20 '18 16:03

Ragnar


3 Answers

There are 2 solutions to solve the "touched is always false" issue.

1) Ensure that input.onBlur is called in your component

For an input:

const { input } = this.props

<input {...input} />

For custom form elements without native onBlur:

const { input: { value, onChange, onBlur } } = this.props

const className = 'checkbox' + (value ? ' checked' : '')

<div
  className={className}
  onClick={() => {
    onChange(!value)
    onBlur()
  }}
/>

2) Declare your form with touchOnChange

const ReduxFormContainer = reduxForm({
  form: 'myForm',
  touchOnChange: true,
})(MyForm)
like image 124
GG. Avatar answered Sep 28 '22 08:09

GG.


The redux-form controls its own props within your <input /> element as long as you use the spread operator to pass those props into your input.

For example, where you are doing const InputItem = ({ spec, meta: { touched, error } }) => ...

Try destructing the input from the Component: const InputItem = ({ input, spec, meta: { touched, error } }) => ...

And where you have your <input ... />, try doing the following:

<input
  {...input}
  className="input"
  type={type}
  placeholder={placeholder}
/>

The redux-form captures any onBlur and onChange events and uses its own methods to change the touched state. You just need to pass those along as shown above.

These are what you need: https://redux-form.com/7.1.2/docs/api/field.md/#input-props

like image 29
pkuzhel Avatar answered Sep 28 '22 07:09

pkuzhel


Another point to consider: I passed {...props} to my custom component, however, touched still remained false. That is because although props contained the input object, my component couldn't deduce onBlur from it. When explicitly stating <CustomComponent {...this.props} onBlur={this.props.input.onBlur}, it worked as expected.

like image 23
Guy Avatar answered Sep 28 '22 06:09

Guy