JavaScript data not loading after async and await

Viewed 363

I'm trying to fetch data from an API and load that data onto a website using React. Currently, I am calling the fetch function using async and await. I printed out the results of the fetch call and all seems to be working properly. What I don't understand is why my studentsJSON array is still empty even though there is an array in data.students.

  const [studentsJSON, setStudentsJSON] = useState([])
  const [students, setStudents] = useState([])

  useEffect(() => {
    async function fetchData() {
      const response = await fetch(URL)
      const data = await response.json()
      console.log(`data.students: ${data.students}`)
      setStudentsJSON(data.students)
      console.log(`studentsJSON: ${studentsJSON}`)
      for (let student of studentsJSON) {
        setStudents(students => [...students, new Student(student)])
      }
      console.log(`students: ${students}`)
    }

    fetchData()
  }, [])

Output:

data.students: [object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
App.js:36 studentsJSON: 
App.js:40 students: 
3 Answers
  1. await response.json() already turns your JSON into a JS data structure so the studentsJSON and setStudentsJSON state really makes no sense.

  2. You might want to reconsider how you update your state. map over the data to create a new array, create a new state array, and then update your student state in one move.

    const newStudents = data.students.map(student => new Student(student));
    const newState = [...students, newStudents].flat();
    setStudents(newState);
    

You can't see your studentsJSON because setState (setStudentsJSON) is an asynchronous operation, and by the time it runs the command console.log the state value studentsJSON is still an empty array.

Instead of logging the result immediately after setState, you can put it inside another useEffect hook:

useEffect(() => {
  console.log(studentsJSON);
}, [studentsJSON]);

Try using promises. This solves the problem of setting state empty.

 const response = await fetch(URL).then((res)=>setStudentsJSON( res.json()))
Related