Is it possible to call an async function inside a constructor in react-native?
Solution 1
You can't do it inside constructor, because constructor can't wait for await
So you can have another function(for example b()
) for all the processes you want to run after async a()
. And you have two choice for doing this:
1- use async/await
:
async componentDidMount() {
try {
await a(); // it will wait here untill function a finishes
} catch(err) {}
b(); // after function a finished, this function will calls
}
2- using .finally
:
componentDidMount() {
// in below line, function `a` will call, and when it finishes, the function inside `.finally` will be notified
a().finally(() => {
b(); // now your function `a` finished and you can call extra process in function `b`
});
}
Solution 2
Asynchronous constructor is a potential antipattern because it doesn't result in behaviour that is expected from it.
Asynchronous side effects are supposed to happen after a component is mounted and thus occur in componentDidMount
, this is what it's for. It's impossible to delay the lifecycle of a component and it's incorrect to think about it in these terms.
It's supposed to work like:
class Foo extends Component
async a() {...}
async componentDidMount() {
await this.a();
}
render() {
(conditionThatIsTrueWhenThereResult) ? (
<div>...the result from a...</div>
) : (
<div>fallback</div>
);
}
}
If it's necessary to keep a component synchronous, a
asynchronous side effect should be moved to parent component that renders a child only when the result from a
is ready to use.
Solution 3
Call a()
in componentDidMount like so:
async componentDidMount() {
await a();
otherFuncions()
}
otherFunctions()
will only be executed after a()
is completed
Solution 4
Async work in constructor is a no no.
Typically you would either have a component that renders a spinner and triggers an async call. Then you can update this component to render something else once the async call is finished.
Another solution is to push that logic up to whoever is rendering this component. The parent should trigger the async call and render the component only after the async call.
As others suggested, you could use componentDidMount
from the component lifecycle to handle this.
See: https://reactjs.org/docs/state-and-lifecycle.html
Related videos on Youtube
Iqbal Jan
I am a Software Engineer and Web developer with 5 years’ experience in the IT- Software industry. I enjoy the detail work and the precision, the complexity and the methodologies involved in the process of Software Applications, Mobile Apps, Web development or database management. I will roll up my Sleeves and contribute in any capacity necessary to help us succeed. As a software engineer I believe in the power of knowledge specially programming which we can do everything we want. I make sure as completely, everything is possible for a programmer in the world of technology.
Updated on November 13, 2020Comments
-
Iqbal Jan over 3 years
I have an async function named
async a()
which has to be run before functioncomponentDidMount()
.So how can I call an async function inside a constructor? Because the constructor function gets run before the componentDidMount function.
I need to be sure my
async a()
completes first in the constructor and then all methods within componentDidMount are executed. -
Iqbal Jan about 5 yearsasync componentDidMount(){} will have their own risk. I would not suggest to make async the componentDidMount func and also I need to completed finish all a() function task befor componentDidMount execute.
-
Iqbal Jan about 5 yearsI've searched about making async function componentDidMount and most of people do not suggested to make async the function componentDidMout like you made it. Please make sure me that using async componentDidMount() is a good way or not.
-
Estus Flask about 5 yearsmost of people do not suggested to make async the function componentDidMout like you made it. - who? It's either this, or doing
a()
in parent component and providing the result through props. Both ways are acceptable. -
Iqbal Jan about 5 yearsthank you to comment and I am sorry that my English is not well I mean in answer to my question you put async keyword befor componentDidMount fucntion and there I dont know it will affect on performance issue weather or not.
-
Iqbal Jan about 5 yearsbecause Most of people in internet do not suggested to use async keyword before componentDidMount
-
Estus Flask about 5 yearsI doubt that there's a lot of people who would emphasize this idea because this is not a big deal. Any way, this suggestion is wrong.
async
doesn't affect the performance, it affects componentDidMount's return value. This is roughly the same thing ascomponentDidMount() { return this.a() }
. The method returns a promise this way, this makes the component more testable and extendable. It's correct to return a promise for chaining anywhere where promises are used, unless this causes problems (and in this case this doesn't cause them). -
Iqbal Jan about 5 yearsHi I've tested this in a simple javascript file but the result is like this: async function a() { setTimeout(() => { console.log('A'); }, 2000); } async function b() { setTimeout(() => { console.log('B') }, 1000); } function c() { console.log("C"); } async function componentDidMount() { await a(); await b(); c(); } componentDidMount(); C B A
-
Iqbal Jan about 5 yearsplease refer to the last answer because in comment the code does not looks well
-
Iqbal Jan about 5 years
-
Iqbal Jan about 5 years
-
Iqbal Jan about 5 years
-
Estus Flask about 5 years
a
andb
resolve immediately. You don't have a promise to chain inside them. In case you want to mimic a delay, it should beasync function a() { await new Promise(resolve => setTimeout(resolve), 2000)); console.log('A') }
. See stackoverflow.com/a/39496056/3731501 -
SiSa about 5 yearsasync functions only will wait if there is
await
inside them or if you returnPromise
inside them -
SiSa about 5 yearsin your example you just setTimeout and both your functions
a
andb
will resolve before your timeout finish