Skip to content
Advertisement

How to render something that is async in React?

I’m making a react app that works with a API that provides data to my App. In my data base I have data about pins on a map. I want to show the info of those pins on my react app, I want them to render. I get that information with axios and this url: http://warm-hamlet-63390.herokuapp.com/pin/list I want to retrieve the info from that url, with axios.get(url), stringify the JSON data and then parse it to an array of pins.

The Problem: My page will be rendered before I get the data back from the server, because axios is async, so I will not be able to show anything. UseEffect and useState won’t work because I need something in the first place (I think).

What i’ve tried: I tried to use useEffect and useState, but as I said, I think I need something in the first place to change it after. I also tried to use await, but await won’t stop the whole React App until it has a response, although it would be nice if there is something that stops the app and waits until I have the array with the info so I can show it on the App then. I tried everything with async. I’m fairly new to React so there might be something basic i’m mssing (?). I’ve been on this for days, I can’t get this to work by any means.. Any help, youtube videos, documentation, examples, is help. Anything. How the hell do I render something that needs to wait for the server respond?

My code:

//function that stores the data in the result array, 
//but result array will only be available after the 
//server response, and after the page is rendered
async function pin(){

  const result = []
  var url = "http://warm-hamlet-63390.herokuapp.com/pin/list"

  const res = await axios.get(url)
  
  console.log(res.data.data);

  if(res.data){
    const txt = JSON.stringify(res.data.data)
    const result = JSON.parse(txt)
    console.log(result);
  }
  return result;
}
class App extends React.Component{

  render(){
    return(
      <div>
        <Pin/>
        <Mapa/>
      </div>
    )
  }
}


export default App

Advertisement

Answer

I don’t fully understand what you are trying to output but how you would usually handle this is with both the useState hook and the useEffect hook see example below.

  //function that stores the data in the result array, 
  //but result array will only be available after the 
  //server response, and after the page is rendered
  const pin = () => {
  const [result, setResults] = useState([]);
  var url = "http://warm-hamlet-63390.herokuapp.com/pin/list"

  useEffect(() => {
    //Attempt to retreive data
    try {
      const res = transformData();

      if (res) {
        // Add any data transformation
        setResults(transformData(res))
      }
      else {
        throw (error)
      }
    }
    catch (error) {
      //Handle error
    }
  }, [])

  // Handle data transformation
  const transformData = async () => {
    const res = await axios.get(url)

    const txt = JSON.stringify(res.data.data)
    const result = JSON.parse(txt)

    return result
  }

  if (!result) {
    // Return something until the data is loaded (usually a loader)
    return null
  }

  // Return whatever you would like to return after response succeeded
  return <></>;
}

This is all assuming that Pin is a component like you have shown in your code, alternatively, the call can be moved up to the parent component and you can add an inline check like below to render the pin and pass some data to it.

{result && <Pin property={someData} />}

Just a bit of background the useEffect hook has an empty dependency array shown at the end “[]” this means it will only run once, then once the data has updated the state this will cause a rerender and the change should be visible in your component

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement