0

Working on a fullstack app I am making a call to the backend that retrieves info from a DB and returns it. Thing is, when I expect to get the value, I only get a Promise {<pending>}. I have verified on the backend code that I actually get a response from the DB and send it back to the frontend so I am not sure why the promise is not being resolved. Any idea/suggestions on this?

Here is the component I am trying to call the backend on and display the information. The console.log is what displays the Promise {<pending>}

getTheAsset = async id => {
    try {
        const response = await this.props.getAsset(id)
            .then(result => {
                console.log("[DisplayAsset] Promise result: ", result);
            });

    } catch(error) {
        console.log("[DisplayAsset] error: ", error);
    }
}

render() {
    const asset = this.getTheAsset(this.props.match.params.id);
    console.log("[DisplayAsset] asset - ", asset);
    return (
        <div className="container">

        </div>
    );
}

The following is the redux action that makes the API call.

export const getAsset = (id) => async dispatch => {
  const response = await axios.get(`http://localhost:8181/api/asset/${id}`);
  dispatch({
    type: GET_ASSET,
    payload: response.data
  });
}

I have included a snapshot of the backend, showing that I am actually getting a value back from the DB. enter image description here

I have also found this great answer, but still did not have much luck applying it to my situation.

Dan
  • 2,020
  • 5
  • 32
  • 55

1 Answers1

5

Async functions always return promises; that's what they do. Async/await exists to simplify the syntax relating to promises, but it doesn't change the fact that promises are involved.

For react components, you need to have a state value which starts off indicating that it hasn't been loaded, then you kick off your async work, and when it finishes you update the state. If necessary, you can render a placeholder while still loading.

state = {
  asset: null,
}

componentDidMount() {
  this.getTheAsset(this.props.match.params.id)
    .then(result => this.setState({ asset: result });
}

render() {
  if (this.state.asset === null) {
    return null; // or some other placeholder.
  } else {
    return (
      <div className="container">

      </div>
    );
  }
}
Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
  • so what I am not fully sure on is why am I getting a pending promise when I know that the result is returned straight away from the backend. Is this normal behaviour for promises? – Dan Sep 17 '19 at 21:19
  • @Dan - you get a pending promise because promises are asynchronous. the statement `console.log("[DisplayAsset] asset - ", asset);` is executed before `axios.get` has even finished making the request, let alone had time to get a response. That's how asynchrony works. – Jaromanda X Sep 17 '19 at 23:20
  • So I have applied the solution provided by@Nicholas (thanks btw!) but `asset` is always null. @Jaromanda, I get what you are saying about asynchronicity and I understand it but is there a way to update the component when the promise is resolved? At the moment it is always pending :( – Dan Sep 18 '19 at 21:08