I'm working on react for last 1 year. The convention which we follow is make an API call in componentDidMount
, fetch the data and setState after the data has come. This will ensure that the component has mounted and setting state will cause a re-render the component but I want to know why we can't setState in componentWillMount
or constructor
The official documentation says that :
componentWillMount() is invoked immediately before mounting occurs. It is called before render(), therefore setting state in this method will not trigger a re-rendering. Avoid introducing any side-effects or subscriptions in this method.
it says setting state in this method will not trigger a re-rendering
, which I don't want while making an API call. If I'm able to get the data and able to set in the state (assuming API calls are really fast) in componentWillMount
or in constructor
and data is present in the first render, why would I want a re-render at all?
and if the API call is slow, then setState
will be async and componentWillMount
has already returned then I'll be able to setState and a re-render should occur.
As a whole, I'm pretty much confused why we shouldn't make API calls in constructor or componentWillMount. Can somebody really help me understand how react works in such case?
Using componentWillMount() to Make API Calls One of the primary usages of componentWillMount() is to make API calls once the component is initiated and configure the values into the state. To make an API call, use an HttpClient such as Axios , or or you can use fetch() to trigger the AJAX call.
Calling API in constructor() or componentWillMount() is not a syntax error but increases code complexity and hampers performance. So, to avoid unnecessary re-rendering and code complexity, it's better to call API after render(), i.e componentDidMount().
As best place and practice for external API calls is React Lifecycle method componentDidMount(), where after the execution of the API call you should update the local state to be triggered new render() method call, then the changes in the updated local state will be applied on the component view.
1. componentWillMount
and re-rendering
Compare this two componentWillMount
methods.
One causes additional re-render, one does not
componentWillMount () { // This will not cause additional re-render this.setState({ name: 'Andrej '}); } componentWillMount () { fetch('http://whatever/profile').then(() => { // This in the other hand will cause additional rerender, // since fetch is async and state is set after request completes. this.setState({ name: 'Andrej '}); }) }
.
.
.
2. Where to invoke API calls?
componentWillMount () { // Is triggered on server and on client as well. // Server won't wait for completion though, nor will be able to trigger re-render // for client. fetch('...') } componentDidMount () { // Is triggered on client, but never on server. // This is a good place to invoke API calls. fetch('...') }
If you are rendering on server and your component does need data for rendering, you should fetch (and wait for completion) outside of component and pass data thru props and render component to string afterwards.
ComponentWillMount
Now that the props and state are set, we finally enter the realm of Life Cycle methods
That means React expects state
to be available as render
function will be called next and code can break if any mentioned state variable is missing which may occur in case of ajax
.
Constructor
This is the place where you define.
So Calling an ajax will not update the values of any state as ajax is async and constructor will not wait for response. Ideally, you should use constructor to set default/initial values.
Ideally these functions should be pure function, only depending on parameters. Bringing ajax
brings side effect to function.
Yes, functions depend on state
and using this.setState
can bring you such issues (You have set value in state but value is missing in state in next called function).
This makes code fragile. If your API is really fast, you can pass this value as an argument and in your component, check if this arg is available. If yes, initialise you state with it. If not, set it to default. Also, in success function of ajax, you can check for ref
of this component. If it exist, component is rendered and you can call its state
using setState
or any setter
(preferred) function.
Also remember, when you say API calls are really fast, your server and processing may be at optimum speed, but you can never be sure with network.
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