Reputation: 355
I am using my forms with react redux. I have the same form for editing and creating a new one.
I want, when opening my form, that, if editing, I put the initial values of the form, from my api.
I have already tried the official documentation, but its not working.
This is my Form:
class Form extends Component {
componentDidMount () {
const tripId = this.props.match.params.uid;
if(tripId){
this.fetchData(tripId);
}
}
fetchData = async (tripId) => {
axios.defaults.headers.common['Authorization'] = 'token';
axios.defaults.headers.common['Accept'] = 'application/vnd.trips.v1+json';
await axios.get(`myurl`)
.then(res => {
const trip = res.data;
this.setState({
trip: trip,
isLoading: false,
initialValues: trip
});
})
console.log('Terminou de carregar')
}
(....)
Form = reduxForm({ form: 'trip', enableReinitialize : true })(Form)
const mapStateToProps = state => {
const { intl, vehicleTypes, users, dialogs, trip } = state
return {
intl,
vehicleTypes,
users,
dialogs,
initialValues: trip
}
}
export default connect(
mapStateToProps, { setDialogIsOpen }
)(injectIntl(withRouter(withTheme()(Form))))
But my initialValues are never filled, and comes always blank. I debuged the code, and I see that my API is loading and setting the state on my fetchData method. So, what Im doing wrong here?
Upvotes: 0
Views: 403
Reputation: 2262
As @d7my said, your mistake is that you are trying to change a prop
through the setState
, they are different things in react world. The fastest way to fix your problem, it would be replacing that:
this.setState({
trip: trip,
isLoading: false,
initialValues: trip
});
For:
this.props.initialize(trip)
The prop initialize
is exported by redux-form to your component to update the form initial state. I made a codesandbox where you can check it working.
Said that, I believe you should change the structure of your component, instead of loading your data inside the component (componentDidMount), you should do it inside a redux action and then update your state. Doing this way, you could easily get the form data from your redux state on mapStateToProps
function and set initialValues
prop instead of use initialize
props, that is much better.
Upvotes: 0
Reputation: 197
First, you're trying to pass initialValues
through this.setState
which is not going to work, reduxForm expect initialValues
to be passed as props
.
One thing to mention, there is a difference between the application state
and component local state
, first one -application state- is clearly managed by redux, and the other one -local component state- is managed by react which you can modify by calling this.setState
so to fix this, you should be dispatching an action when you receive the data from your api, and you update your props in mapStateToProps
your code should look like:
class Form extends Component {
componentDidMount () {
const tripId = this.props.match.params.uid;
if(tripId){
this.fetchData(tripId);
}
}
fetchData = async (tripId) => {
await axios.get(`https://toptal-backend-fmaymone.c9users.io/trips/${tripId}`)
.then(res => {
const trip = res.data;
this.props.fillTheForm(trip);
})
console.log('Terminou de carregar')
}
(....)
Form = reduxForm({ form: 'trip', enableReinitialize : true })(Form)
const mapStateToProps = state => {
const { intl, vehicleTypes, users, dialogs, trip } = state
return {
intl,
vehicleTypes,
users,
dialogs,
initialValues: trip
}
}
const fillTheForm = (dispatch) => (trip) => {
// here you dispatch the action and update your application state
// in your reducer when this action is dispatched,
// then mapStateToProps should be called and the data you just
// passed in your reducer should be in (state)
dispatch()
}
export default connect(
mapStateToProps, { setDialogIsOpen, fillTheForm }
)(injectIntl(withRouter(withTheme()(Form))))
Upvotes: 1