22

My input field is not updating on key press:

import React, { Component, PropTypes } from 'react';

import { Field, reduxForm } from 'redux-form';

class CitySelector extends Component {
  render() {
    const { isFetching, pristine, submitting, handleSubmit } = this.props;

    return (
      <form className="form-horizontal col-xs-offset-1" onSubmit={handleSubmit(this.fetchWeather)}>
        <div className="form-group">
          <div className="col-md-4 col-xs-4">
            <Field name="city"
                   component={city =>
                     <input type="text" className="form-control" {...city.input} placeholder="enter a city for a 5 day forecast"/>
                   }
            />
          </div>
          <div className="col-md-3 col-xs-3">
            <button type="submit" className="btn btn-success">Submit</button>
          </div>
        </div>
      </form>
    );
  }
}

export default reduxForm({
  form: 'cityForm'
})(CitySelector);

Do I need to supply an onChange handler for text inputs?

5 Answers 5

73

I was having the same problem and my mistake was very simple.

Here's what I had:

import { combineReducers } from 'redux';
import { reducer as forms } from 'redux-form';

import otherReducer from './otherReducer';

export default combineReducers({ otherReducer, forms });

Notice that I was importing redux-form reducer as forms and passing it as is to my combineReducers (like I did with otherReducer) using ES6 Object property value shorthand.

The problem is that the key used to pass redux-form reducer to our combineReducers MUST be named form, so we have to change it to:

export default combineReducers({ customer, form: forms });

or

import { reducer as form } from 'redux-form';
export default combineReducers({ otherReducer, form });

Hope this helps someone else...

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

3 Comments

nice catch on the key bit
The docs need to have this information. Doing the 'get started' guide leads you right into the trap. This is the fix.
I really forget this 'import { reducer as forms } from 'redux-form';
27

If you are using immutable data structures, instead of:

import { reduxForm } from 'redux-form';

use this:

import { reduxForm } from 'redux-form/immutable';

See here for more info http://redux-form.com/6.7.0/examples/immutable/

2 Comments

Thanks, I wasted a few hours wondering why my inputs were not updating!
thanks, this was what was going on wrong with me. if you happen to use react-boilerplate, you would have this problem.
3

I was just having an issue similar to this question, except my form wasn't submitting and my validate function also wasn't firing.

It was due to this:

I changed it from input to something else and it totally broke redux-form SILENTLY

const TextInput = ({
    input,                                                 <--- DO NOT CHANGE THIS
    placeholder,
    type,
    meta: { touched, error, warning }
  }) => {
    return (
      <div className="row-md">
          <input
            placeholder={placeholder}
            type={type}
            className="form-text-input primary-border"
            {...input}                                     <--- OR THIS
          />
          {touched && ((error && <span>{error}</span>) || (warning && <span>{warning}</span>))}
      </div>
    )
}

Here's the rest of my input if anyone wants to study it:

<Field
  component={TextInput}
  type="tel"
  name="person_tel"
  placeholder="Mobile Phone Number"
  value={this.props.person_tel}
  onChange={(value) => this.props.updateField({ prop: 'person_tel', value })}
/>

Comments

1

If you supply a custom input component to the Field, then yes you have to call onChange passed within input prop to your component. In fact, you almost got it right by spreading city.input, but there's a catch.

When you define a stateless component (or just any function) inside render() method, it is recreated upon every render. And because this stateless component is passed as a prop (component) to Field, it forces Field to render after each recreation. So, your input is going to lose focus whenever CitySelector component renders, thus, no key presses will be captured.

You should extract your stateless component into a separate definition:

const myInput = ({ input }) => (
  <input type="text" className="form-control" {...input} placeholder="enter a city for a 5 day forecast" />
);

class CitySelector extends Component {
  render() {
    const { isFetching, pristine, submitting, handleSubmit } = this.props;

    return (
      <form className="form-horizontal col-xs-offset-1" onSubmit={handleSubmit(this.fetchWeather)}>
        <div className="form-group">
          <div className="col-md-4 col-xs-4">
            <Field name="city" component={myInput} />
          </div>
          <div className="col-md-3 col-xs-3">
            <button type="submit" className="btn btn-success">Submit</button>
          </div>
        </div>
      </form>
    );
  }
}

It also makes your code more legible.

You can find more info on that problem in official docs of Redux Form. Note that you could probably use the default input without creating your own, take a look at simple form example.

9 Comments

Does my reducer need to update a property called city?
Well, no, Redux Form manages state updates on its own. I can't really find the source of your problem here. Can you see any errors in the console?
No errors in the console and I can see this action getting logged: action Object {type: "redux-form/CHANGE", meta: Object, payload: "a"}
I would not have thought I need to handle redux-form/CHANGE
If I type a repeatedly I just get the same action with only 1 letter in the payload which would suggest the store is not getting updated correctly
|
0

I found out/ my problem was my

form: formReducer

was not in rootReducer.

formReducer must be on top. My case:

const rootReducer = combineReducers({
   general: generalReducer,
   data: combineReducers({
       user:userReducer,
       todoReducer
   }),
       form: formReducer
   });

Comments

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.