Reputation: 28770
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?
Upvotes: 22
Views: 21892
Reputation: 11
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
});
Upvotes: 0
Reputation: 17132
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 })}
/>
Upvotes: 3
Reputation: 1636
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/
Upvotes: 27
Reputation: 6240
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...
Upvotes: 73
Reputation: 1062
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.
Upvotes: 1