Search code examples
javascriptreactjspromiserequest-promise

Using Async await in react component


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>
        )
    }

}


Solution

  • 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
    
    }