Using Async await in react component

20,779

I think you need more about async/await in JS.

An async function always return a promise. So x in Wrapper is a promise. Because you don't use await/async.

It should be like this.

async Wrapper = (body) => {
    try{
        let x = await this.Send(body); // <-- missing await here
        return x;
    }catch(e){console.log(e)}
}

But then, the code in render doesn't work. because this.Wrapper() now returns a promise. -> returnData is a promise. And the render method can't be async function :)

render(props) {
    //... 
    const returnData = this.Wrapper(jsonBody) // <-- returnData here is a promise.
    //...

So to make things work.

You have to use state. Call the this.Wrapper in componentDidMount or componentDidUpdate. For example:

constructor() {
    // ...
    this.state = { returnData: null }
}
async componentDidMount() {
   const returnData = await this.Post(...); // Using await to get the result of async func
   this.setState({ returnData });
}

async Post(body) {
  try{
    const options = {
      method: 'POST',
      uri: 'XXXXXXXXXXXXXXXXXXXX',
      body: body
    }
    return rp(options); // define await then return is unnecessary 
  }catch(e){console.warn(e)}
}

render() {
     const { returnData } = this.state;
    // ... Do the rest

}
Share:
20,779
Scottt
Author by

Scottt

Updated on July 20, 2022

Comments

  • Scottt
    Scottt almost 2 years

    So I've created a component that shoots off post requests with props that I provide.

    Although I'm familiar with Async await I for some reason can't seem to get this to return the actual value of the fulfilled promise and instead just get pending.

    I've tried wrapping with more functions as I understand the promise is not being resolved.

    I feel like I'm missing something.

    A sample of my code below

    export default class PostController extends React.Component {
    constructor(props) {
        super(props)
    }
    Wrapper = (body) => {
        try{
            let x = this.Send(body);
            return x;
            console.log(x)
        }catch(e){console.log(e)}
    }
    Send = async (body) => {
            try{
                let data = await this.Post(body);
                return data;
            }catch(e){console.warn(e)}       
    }
    Post = async (body) => {
        try{
            const options = {
                method: 'POST',
                uri: 'XXXXXXXXXXXXXXXXXXXX',
                body: body
            }
            const data = await rp(options);
            return data; 
        }catch(e){console.warn(e)}
    }
    render(props) {
        let jsonBody = JSON.stringify(this.props.data)
        const returnData = this.Wrapper(jsonBody)
        console.log(returnData)
    
            return(
                <div>
                     {(!this.props.data.pw) ? 'Retrieved Password: ' + returnData.message : 'Generated PassWord!:' + returnData.message }
                </div>
            )
        }
    

    }

  • Scottt
    Scottt about 5 years
    Excellent! Didn't realize could use componentdidmount like that! I have a lot to learn!
  • Tan Dat
    Tan Dat about 5 years
    @Scottt: if the answer is what you need. go mark it as correct answer!
  • Sebastian Nielsen
    Sebastian Nielsen almost 3 years
    But won't this unnecessarily fetch posts for each mount? Which will result in very inefficient code.
  • Suisse
    Suisse almost 3 years
    Unexpected reserved word 'await'. I am using it in async componentDidMount() strange!
  • Tan Dat
    Tan Dat almost 3 years
    @Suisse maybe you're using old version that does not support async await?
  • Suisse
    Suisse almost 3 years
    @TanDat older version of react? O_O I used npx create-react-app my-app - don't think that is an old version there. strange.