Using Async await in react component
Asked Answered
A

2

14

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

}

Archetype answered 1/3, 2019 at 1:7 Comment(2)
Can you show what rp(options) is, and why it awaits something?...Marou
request promise, its a library that wraps the regular request library in a promise.Archetype
S
11

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

}
Shin answered 1/3, 2019 at 2:12 Comment(6)
Excellent! Didn't realize could use componentdidmount like that! I have a lot to learn!Archetype
@Scottt: if the answer is what you need. go mark it as correct answer!Shin
But won't this unnecessarily fetch posts for each mount? Which will result in very inefficient code.Toehold
Unexpected reserved word 'await'. I am using it in async componentDidMount() strange!Zoster
@Zoster maybe you're using old version that does not support async await?Shin
@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.Zoster
P
0

I believe you should try marking Wrapper function as async and awaiting on it before console logging returnData. Also await on Send() inside Wrapper.

Poetess answered 1/3, 2019 at 1:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.