Search code examples
reactjsapiinfinite-scroll

SWAPI React - InfiniteScroll


I'm trying to play with the Star Wars API and set Infinite Scroll, but I can't handle adding more pages. I'm displaying the first page.

I know I'm doing something wrong in the getMorePeople function, but I have no idea how to change it. Could someone suggest something?

import {useEffect, useState} from "react";
import axios from "axios";

const swapi = axios.create({
    baseURL: "https://swapi.dev/api/"
});

const InfiniteScroll = () => {
    const [people, setPeople] = useState([]);
    const [page, setPage] = useState(1);

    const peopleApi = swapi.get(`people/?page=${page}`);

    const fetchPeople = async () => {
        const response = await peopleApi;
        const transformPeople = response.data.results.map(PeopleObject => {
            return {
                name: PeopleObject.name,
                height: PeopleObject.height,
                hair_color: PeopleObject.hair_color,
                skin_color: PeopleObject.skin_color,
                birth_year: PeopleObject.birth_year
            }
        })
        setPeople(transformPeople);
    }

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


    const getMorePeople = async (page, people = []) => {
       const {next, results} = await fetchPeople(people);
       people = [...people, ...results];
       if (next !== null) {
         return getMorePeople(next, people);
       }
       return people;
    }


    return (
        <>
              <div>
                {people.map((onePerson) => {
                    return (
                        <div key={onePerson.name}>
                            <p: {onePerson.name}</p>
                            <p>Height: {onePerson.height}</p>
                            <p>Hair color: {onePerson.hair_color}</p>
                            <p>Skin color: {onePerson.skin_color}</p>
                            <p>Birth year: {onePerson.birth_year}</p>
                        </div>
                    )
                })}
                <button onClick={getMorePeople}>Next</button>
            </div>
        </>
    )
};

export default InfiniteScroll;

Solution

  • Check if this suits your needs:

    import { useEffect, useState } from "react";
    import axios from "axios";
    
    const swapi = axios.create({
        baseURL: "https://swapi.dev/api/"
    });
    
    const InfiniteScroll = () => {
        const [people, setPeople] = useState([]);
        const [page, setPage] = useState(1);
    
        const fetchPeople = async (page = 1) => {
            const response = await swapi.get(`people/?page=${page}`);;
            const transformPeople = response.data.results.map(PeopleObject => {
                return {
                    name: PeopleObject.name,
                    height: PeopleObject.height,
                    hair_color: PeopleObject.hair_color,
                    skin_color: PeopleObject.skin_color,
                    birth_year: PeopleObject.birth_year
                }
            })
            setPeople([...people, ...transformPeople]); //append the new page into the existing array
        }
    
        useEffect(() => {
            fetchPeople();
        }, []);
    
    
        const getMorePeople = async () => {
            const nextPage = page + 1;
            setPage(nextPage);
            fetchPeople(nextPage);
        }
    
        return (
            <>
                <div>
                    {people.map((onePerson) => {
                        return (
                            <div key={onePerson.name}>
                                <p> {onePerson.name}</p>
                                <p>Height: {onePerson.height}</p>
                                <p>Hair color: {onePerson.hair_color}</p>
                                <p>Skin color: {onePerson.skin_color}</p>
                                <p>Birth year: {onePerson.birth_year}</p>
                                <br />
                            </div>
                        )
                    })}
                    <button onClick={getMorePeople}>Next</button>
                </div>
            </>
        )
    };
    
    export default InfiniteScroll;