0

So I have a React App that comunicates with my API that returns JSON data, and I want to parse that data to my results array. The problem is that axios is async, so when I execute my function, results array will be returned before it gets parsed the data from the response, and it will log as empty, so I can't use my response array in the rest of the project. How do I make the axios expression in my function to wait until it has a response and then execute the rest?

Function:

async function pin(){

  const result = []
  var url = "my_api_url"

  axios.get(url)
  .then((res)=>{
    if(res.data){
          result = JSON.parse(res.data.data)
    }
  })
  console.log(result);
  return result;
}

This is the react right after the function:

export default function App(){

  const{isLoaded, loadError} = useLoadScript({
    googleMapsApiKey: "my_api_key",
    libraries,
  })

  const [markers, setMarkers] = React.useState([]);
  if(loadError) return "Erro a carregar o mapa"
  if(!isLoaded) return "Carregando"

  const result = []

  return <div>
    {pin()}
    <GoogleMap 
    mapContainerStyle={mapContainerStyle} 
    zoom={11} 
    center={center}
    >
    </GoogleMap>
  </div>
}

I'm just calling the function here to see if it's OK, I haven't implemented it yet. I have already tried to switch .then to .await but I get the error Objects are not valid as a React child (found: [object Promise])

Enguias
  • 73
  • 2
  • 7
  • did `await` not work instead of the promise (`then`)? – Nikki9696 Jun 11 '21 at 22:52
  • No... I get this: ```Error: Objects are not valid as a React child (found: [object Promise]).``` – Enguias Jun 11 '21 at 22:57
  • 1
    if you await, the return type should not change - where did you put the await? Can you edit your question with what you tried? – Nikki9696 Jun 11 '21 at 22:59
  • By the way, you should be able to remove the for loop. – Shivam Jun 11 '21 at 23:01
  • i edited it now – Enguias Jun 11 '21 at 23:06
  • "*I have already tried to switch .then to .await*" - please show us the code of that attempt. Notice that the error message you're getting is not related to the `pin` function, it comes from some react code that you haven't shown us yet (probably some component that calls `pin()`?). – Bergi Jun 11 '21 at 23:15
  • ah ha - yeah you can't just output that there - it has to be in an element – Nikki9696 Jun 11 '21 at 23:16
  • the code of the attempt is literally what I have there except ```.there``` is replaced by ```.await```... I edited it and now I posted the react too – Enguias Jun 11 '21 at 23:17
  • deleting my answer because I'm an idiot =) – Nikki9696 Jun 11 '21 at 23:38
  • Hahaha no problem x) – Enguias Jun 11 '21 at 23:39
  • You are getting the error because you are trying to use the result of an asynchronous operation in a synchronous function: `{pin()}` is a promise object, not the parsed data returned from the axios call. `App` probably needs to be an `async` function. – traktor Jun 11 '21 at 23:39
  • 1
    Does this answer your question? [How to return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – traktor Jun 11 '21 at 23:40
  • Yeah i've already read that, it helped, this is post is after a problem that I had with something similar to that, thanks anyway! – Enguias Jun 11 '21 at 23:42
  • @Enguias this post is committing the same error covered in the link suggested. – traktor Jun 11 '21 at 23:44

2 Answers2

2

Okay, so this has been a fun learning experience for me, as I am also new to React.

This sample worked for me. I don't have an example where it's an array but you see how I had to use the state to track things and make it show up as a json string so it would render. I assume you want the pin function outside the component for some reason so I passed in the state handler.

Hopefully this helps you out.

import * as React from 'react';
import './App.css';
import axios from 'axios';


const pin = async (handler) => {
  let result = []
  var url = "https://jsonplaceholder.typicode.com/todos/1"
  const res = await axios.get(url);
  result[1] = JSON.stringify(res.data);
  handler(result);
}

function App() {
   const [results, setResults] = React.useState('');

  React.useEffect(() => {
    if (!results) {
        pin(setResults);
    }
  },[results]);

  return (
    <div>
      <h1>some header</h1>
      <div>{results}</div>
    </div>
  );
}

export default App;
Nikki9696
  • 6,260
  • 1
  • 28
  • 23
1

You can return the promise in your pin function like so:

async function pin(){

  const result = []
  var url = "my_api_url"

  return axios.get(url)
}

Then wherever you are calling the pin function, you can chain your .then. Example:

pin()
  .then((res)=>{
    // do something with the data
  })
mattyp1007
  • 11
  • 1
  • thanks for answering, but I get the same error: ```Objects are not valid as a React child (found: [object Promise])``` – Enguias Jun 11 '21 at 23:09