-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
(I'm fairly new to React and Redux, and so I'm still trying to figure out the best coding patterns and practices, so apologies if this is obvious to everybody but me.)
I'm working on a React/Redux app which has several components which request their own data. For example, when a "/users" route is invoked, the <Users />
component gets invoked, and that component triggers an async call (via redux-thunk) which updates the Redux store with the fetched user data, and then ultimately the users data appears within the <Users />
component.
The render()
function within <Users />
is just watching for changes to this.props
. The parent of <Users />
watches the Redux store, and of course passes the user data down.
This all worked fine in React 0.13. Or at least it "worked" with no errors/warnings in the console. I updated to 0.14 late last week, and started to see the following warning in the logs:
Warning: setState(...): Cannot update during an existing state transition (such as within render
). Render methods should be a pure function of props and state.
I floundered around, and finally figured out that the problem was that my async data request was in the class constructor. Something like this:
constructor(props) {
super(props);
fetchUsers();
}
render() {
return ( do the stuff to output the user data );
}
If I moved the fetchUsers()
call to either componentDidMount()
or componentWillMount()
, everything functioned properly, and the error went away.
So my question is ultimately this: what is going on here? What is the functional difference between these three functions? My (obviously incorrect) assumption was that I should request the data when the class gets initialized, which is why I put the async call in constructor()
. Why does that not work, why do those two React lifecycle methods work, and which one of the two is preferable? React's docs say componentDidMount()
is the right method to use, but I would think I'd want the data before the component is mounted, which make me think componentWillMount()
should be the method I use.