Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
284 views
in Technique[技术] by (71.8m points)

reactjs - Best way to request unknown number of API pages in useEffect hook

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;
question from:https://stackoverflow.com/questions/65873133/best-way-to-request-unknown-number-of-api-pages-in-useeffect-hook

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Unnecessary hooks.. work with api data (Recursion call)

I make a codesandbox with mock data to save api request (for development)

https://codesandbox.io/s/elastic-field-i89yu

but the main idea is here:

using next key in api response: enter image description here

You can make it more elegant:

function GetAllPeople() {
  const [people, setPeople] = useState([]);

  const requestData = useCallback((url = 'https://swapi.dev/api/people/?page=1') => (
    fetch(url)
      .then(async res => {
        const response = await res.json();
        setPeople(prevState => prevState.concat(response.results));
        if (response.next) {
          requestData(response.next.replace("http://", "https://"));
        } else {
          console.log("Finish !");
        }
      }).catch(err => {
        throw err;
      })
  ), []);

  useEffect(() => {
    requestData();
  }, [requestData]);

  return (
    ...
  )
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...