I'm trying to write a React functional component that requests a list of people exposed across multiple pages in an API:
https://swapi.dev/api/people/?page=9
I know there are currently nine pages, but this might change in the future, so I want my component to keep requesting pages until there are no more, and to accumulate and store the people in the "results" bit of each response body. I'm trying to do this with useState and useEffect hooks.
Is there a common way of solving this problem that's generally considered the best approach? Could someone show me how to modify my existing code to get it working in the optimal way please?
My current code causes the browser to get stuck endlessly loading.
Was I wrong to try and handle the entire process in the first and only execution of useEffect? Should my useState have a dependency array that gets passed page so that useEffect executes again every time page is updated?
import React, { useState, useEffect } from 'react';
function GetAllPeople() {
const [page, setPage] = useState(1)
const [people, setPeople] = useState([]);
const [gotEveryone, setGotEveryone] = useState(false)
const [error, setError] = useState(null)
const requestData = () => (
fetch(`https://swapi.dev/api/people/?page=${page}`)
.then(res => {
if (res.ok) {
let response = res.json()
setPeople(people.concat(response.results))
setPage(page + 1)
} else if(res.status === 404) {
setGotEveryone(true)
} else {
setError(res.status)
return Promise.reject('some other error: ' + res.status)
}
})
)
useEffect(() => {
while(gotEveryone === false) {
if (!error) {
requestData()
}
}
})
return (
<div>
<ul>
{people.map((person, index) =>
<li key={index}>
{person.name}
</li>
)}
</ul>
</div>
)
}
export default GetAllPeople;
