Jeffrey
Jeffrey

Reputation: 63

How to wait for Fetch to finish grabbing data before continueing

I am trying to figure out how to use the FetchAPI to grab data from an URL and display it on my page. The data is a list of students, however I believe because it is asynchronous, my page attempts to render my iterative loop on incomplete data and so it throws an error, saying that my variable is not iterable (when it should be). This is what my code looks like

function StudentDisplay(){

    const user = "URL that I won't disclose but it works as it should be";
    fetch(user)
    .then(res => res.json())
    .then(data=> DisplayStudents(data.students));

    const DisplayStudents = students => {
        console.log("blah");
        console.log(students);
        let result = []
        students.forEach(student => {
            console.log(student);
            const studentElement = <>Hello World</>;
            result.push(studentElement);
        })
        return <span>{result}</span>
    }

    return(
        <DisplayStudents/>
    );
}

this is what my console looks like when attempting to print stuff out:

blah
{}
blah //I don't quite understand why this is printing twice
{}
//Long Error complaining that 'students.forEach' is not a function and some other stuff
blah
[Array]
Student object
Student object
...
blah // Again I don't quite understand why it gets printed twice
blah
[Array]
Student object
Student object
...

I've also tried xhr and axios, but I don't really understand how any of these work because they are all giving similar errors, so I'd like to stick with fetch. Can someone explain what is happening and how can I get this to work?

Upvotes: 0

Views: 1022

Answers (3)

Denis Malykhin
Denis Malykhin

Reputation: 347

Shortly, you should isolate API requests somehow and store the results in the proper place. There are multiple ways to do so, but probably the basic and modern way is to use hooks:

import {useState, useEffect} from 'react'
const user = 'URL that i won't disclose but it works as it should be';

function StudentDisplay(){
    const [students, setStudents] = useState([])
    
    useEffect(() => {
      fetch(user)
        .then(res => res.json())
        .then(students => setStudents(students));
    }, [])


    return(
        <ul>
          {students.map(s => <li key={s.id}>{s.name}</li>)}
        </ul>
    );
}

You can find more information about hooks there https://reactjs.org/docs/hooks-faq.html

Upvotes: 1

Gowtham Raj J
Gowtham Raj J

Reputation: 967

Students is inside your response object. You are not trying to loop over it, but the response Object, that's why you are getting an error. You could

fetch(user)
    .then(res => res.json())
    .then(({students}) => DisplayStudents(students));

or inside your DisplayStudents

const DisplayStudents = resp => {
        console.log("blah");
        console.log(resp);
        let result = []
        resp.students.forEach(student => {
            console.log(student);
            const studentElement = <>Hello World</>;
            result.push(studentElement);
        })
        return <span>{result}</span>
    }

Upvotes: 0

fonzane
fonzane

Reputation: 440

You can make the function async by writing the async keyword infront of the function and store the result in a variable like const result = await fetch() (also omit .then)

Upvotes: 0

Related Questions