While building my React and Redux project in bootcamp, I had a difficult time understanding the fundamental differences between the componentWillMount()
and componentDidMount()
methods. I kept getting frustrated when one would work, yet I didn’t understand how or why.
componentWillMount()
One big snag that I didn’t realize until an online study group session is that componentWillMount()
was deprecated in 2018. While you can continue to use it (until React 17.0), it isn’t best practice because it is not safe for async rendering. If you do choose to continue to use it, you should use UNSAFE_componentWillMount()
.
The Reason
Using a fetch call within componentWillMount()
causes the component to render with empty data at first, because componentWillMount()
will NOT return before the first render of the component.
Due to the fact that JavaScript events are async, when you make an API call, the browser continues to do other work while the call is still in motion. With React, while a component is rendering it doesn’t wait for componentWillMount()
to finish, so the component continues to render.
With all that being said, you would need to to create a component that still looks presentable without the data that you are hoping to display. There is no way (not even a timer) to stop the component from rendering until the data is present.
When I was building my project, I didn’t know about the deprecation of componentWillMount()
and I didn’t understand why I kept getting the “cannot read property ‘map’ of undefined” error. I was so confused because I had an array and it should be getting populated by data, but it wasn’t.
Turns out this makes complete and total sense since the component is rendered with empty data at first, so the array was empty and couldn’t be iterated over. It was only at this point that I learned that it is best practice to use componentDidMount()
.
componentDidMount()
The best place to make calls to fetch data is within componentDidMount()
. componentDidMount()
is only called once, on the client, compared to componentWillMount()
which is called twice, once to the server and once on the client. It is called after the initial render when the client received data from the server and before the data is displayed in the browser. Due to the fact that the data won’t be loaded until after the initial render, the developer NEEDS to set up the components initial state properly.
On a side note, with componentDidMount()
you can use a timer and have the data updated every so often without the user ever having to refresh the page. I’d say that is a really neat feature that can be useful in projects/websites.
Final Notes
Once I learned that I should be using componentDidMount()
, my project really came to life. Everything else was working properly and that was my final error to fix. It was amazing learning that it was this simple of a problem, it just seemed complex to me at first. The more I write about it, the more it becomes clear. I hope that by the time you’ve gotten to this point you feel like you have a better grasp on the topic as well. If you need any extra information, please feel free to look at my resources, they are great articles!
Sources
componentDidMount() v/s componentWillMount() — React
Where to Fetch Data: componentWillMount vs componentDidMount
componentWillMount is deprecated in react 16.3
What’s new in React 16.3(.0-alpha)
Top comments (4)
From developer standpoint I'd add that
componentWillMount
is roughly the equivalent of just doing stuff inconstructor
. The difference between using these is very small. I guesscomponentWillMount
only existed because of historicalReact.createClass
reasons when you didn't yet have aconstructor
in React classes - and onceconstructor
became available with ES6 it pretty much removed any need to havingcomponentWillMount
.The way I think this is that
constructor
is the place where you put together the initial internal state of your component. This will be the same state for both server rendered and initial browser render. Once browser kicks in then you have all the other lifecycle methods to live with fromcomponentDidMount
all the way tocomponentWillUnmount
- all of which are not available when rendering server stuff.I don't understand this part: componentWillMount() which is called twice, once to the server and once on the client. It is called after the initial render when the client received data from the server and before the data is displayed in the browser.
I've read this reason at a number of places, but I don't understand what server are you talking about ?
Also am using hooks now but isn't it so that even with componentDidMount/useEffect with empty dependency array, I already have the component rendered once ? I mean, I set the state such that values are undefined initially and then I show a loader or something.
So what's the difference when you say that when componentWillUpdate has made an API call, component has already rendered once before the response comes back and state is set ? can't I set the initial state such that I get a blank view until componentWillUpdate's fetch call brings me data ?
Thank you for your help !! Greetings from Paris !
Wow! I was so confused. Thanks a lot for your help. Love from Sri Lanka