Is it possible to call an async function inside a constructor in react-native?

20,819

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

Share:
20,819

Related videos on Youtube

Iqbal Jan
Author by

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, 2020

Comments

  • Iqbal Jan
    Iqbal Jan over 3 years

    I have an async function named async a() which has to be run before function componentDidMount().

    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
    Iqbal Jan about 5 years
    async 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
    Iqbal Jan about 5 years
    I'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
    Estus Flask about 5 years
    most 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
    Iqbal Jan about 5 years
    thank 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
    Iqbal Jan about 5 years
    because Most of people in internet do not suggested to use async keyword before componentDidMount
  • Estus Flask
    Estus Flask about 5 years
    I 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 as componentDidMount() { 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
    Iqbal Jan about 5 years
    Hi 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
    Iqbal Jan about 5 years
    please refer to the last answer because in comment the code does not looks well
  • Iqbal Jan
    Iqbal Jan about 5 years
  • Iqbal Jan
    Iqbal Jan about 5 years
  • Iqbal Jan
    Iqbal Jan about 5 years
  • Estus Flask
    Estus Flask about 5 years
    a and b resolve immediately. You don't have a promise to chain inside them. In case you want to mimic a delay, it should be async function a() { await new Promise(resolve => setTimeout(resolve), 2000)); console.log('A') } . See stackoverflow.com/a/39496056/3731501
  • SiSa
    SiSa about 5 years
    async functions only will wait if there is await inside them or if you return Promise inside them
  • SiSa
    SiSa about 5 years
    in your example you just setTimeout and both your functions a and b will resolve before your timeout finish