I am having some issues with setting the inital form field values using redux-form.
I am using redux-form v6.0.0-rc.3 and react v15.3.0.
So here's my issue, I have a grid of users and when a user row is clicked on, I am navigating to an edit users page and including the users id in the url. Then on the edit users page, I am grabbing the id and calling fetchUser(this.props.params.id) which is an action creator that returns this.state.users. I am then attempting to set the forms inital values by calling:
function mapStateToProps(state) {
return { initialValues: state.users.user }
}
By my understanding, this should set the initialValues to state.users.user and whenever this state is updated the initialValues should be updated as well. This is not the case for me. InitialValues is being set to the previously clicked on user row (i.e the previous state for this.state.users.user). So I decided to test this and add a button to this component and when its clicked I am calling fetchUser again with a user id hard coded in:
this.props.fetchUser('75e585aa-480b-496a-b852-82a541aa0ca3');
This is updating the state correctly but the values for initialValues do not change. It is not getting updated when the state is updated. I tested this exact same process on an older version of redux-form and it worked as expected.
Am I doing something wrong here or is this an issue with the version I am using.
Users Edit Form -
class UsersShowForm extends Component {
componentWillMount() {
this.props.fetchUser(this.props.params.id);
}
onSubmit(props){
console.log('submitting');
}
changeUser() {
this.props.fetchUser('75e585aa-480b-496a-b852-82a541aa0ca3');
}
renderTextField(field) {
return (
<TextField
floatingLabelText={field.input.label}
errorText={field.touched && field.error}
fullWidth={true}
{...field.input}
/>)
}
render() {
const { handleSubmit, submitting, pristine } = this.props;
return(
<div>
<form onSubmit={handleSubmit(this.onSubmit.bind(this))} className="mdl-cell mdl-cell--12-col">
<Field name="emailAddress" component={this.renderTextField} label="Email Address"/>
<Field name="firstName" component={this.renderTextField} label="First Name"/>
<Field name="lastName" component={this.renderTextField} label="Last Name"/>
</form>
<RaisedButton onClick={this.changeUser.bind(this)} label="Primary" primary={true} />
</div>
);
}
}
function mapStateToProps(state) {
return { initialValues: state.users.user }
}
UsersShowForm = reduxForm({
form: 'UsersShowForm'
})(UsersShowForm)
UsersShowForm = connect(
mapStateToProps,
actions
)(UsersShowForm)
export default UsersShowForm
Users Reducer -
import {
FETCH_USERS,
FETCH_USER
} from '../actions/types';
const INITIAL_STATE = { all: [], user: {} };
export default function(state = { INITIAL_STATE }, action) {
switch (action.type) {
case FETCH_USERS:
return {...state, all: action.payload };
case FETCH_USER:
return {...state, user: action.payload };
default:
return state;
}
}
Reducer Index -
import { combineReducers } from 'redux';
import { reducer as formReducer } from 'redux-form';
import usersReducer from './users_reducer';
const rootReducer = combineReducers({
form: formReducer,
users: usersReducer
});
export default rootReducer;
I was facing the same problem after update to redux-form v6.0.0-rc.4.
I solved setting enableReinitialize to true
UsersShowForm = reduxForm({
form: 'UsersShowForm',
enableReinitialize: true
})(UsersShowForm)
To pre-fill a redux-form
form with data from a resource, you would use the initialValues
prop which is read automatically when decorating the component/container with the reduxForm
connector. It's important that the keys in the initialValues
match the name
on the form fields.
Note: It is necessary to first apply the reduxForm()
decorator, and then the connect()
from redux. It will not work the other way around.
Using redux-form 7.2.3:
const connectedReduxForm = reduxForm({
form: 'someUniqueFormId',
// resets the values every time the state changes
// use only if you need to re-populate when the state changes
//enableReinitialize : true
})(UserForm);
export default connect(
(state) => {
// map state to props
// important: initialValues prop will be read by redux-form
// the keys must match the `name` property of the each form field
initialValues: state.user
},
{ fetchUser } // map dispatch to props
)(connectedReduxForm)
From the official documentation:
Values provided to the initialValues prop or reduxForm() config parameter will be loaded into the form state and treated thereafter as "pristine". They will also be the values that will be returned to when reset() is dispatched. In addition to saving the "pristine" values, initializing your form will overwrite any existing values.
Find more information and a complete example in the official documentation
In my case I have Redux Form, 2 Route with small url param changes. When Switching between component Props were not getting updated. It kept showing blank form.
Example: baseurl/:id/personal -> baseurl/:id/employment
After debugging I found that mapStateToProps is not firing sometime where Initial values are set.
<React.Fragment>
<Route
exact={true}
path="/path1"
component={PersonalDetails}
key="personal"
/>
<Route
exact={true}
path="/path1/employment"
component={Employment}
key="employment"
/>
</React.Fragment>
setting destroyOnUnmount to false mapStateToProps fixed my issue, where its default is true.
enableReinitialize: true,
destroyOnUnmount: false
Example using above :
UsersShowForm = reduxForm({
form: 'UsersShowForm',
enableReinitialize: true,
destroyOnUnmount: false
})(UsersShowForm)
Read more : destroyOnMount
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With