trainReact.com
||

10. Render Pokemon List using React Query Custom Hook

Medium
Category: React Query
React QueryCustom HooksInfinite ScrollPokeAPI

Problem Description

You are provided with a custom React hook useFetchPokemon that fetches Pokémon data from the PokéAPI. The current PokemonList component is incomplete and lacks the functionality to display and manage the list of Pokémon effectively.

Your Task

Your goal is to complete the PokemonList component to create a fully functional Pokémon list with the following features:

  1. Fetch and Display Pokémon: Use the useFetchPokemon custom hook to fetch Pokémon data and display the list of Pokémon names.

  2. Implement Pagination: Allow users to load more Pokémon by clicking a "Load More" button. This should fetch the next page of Pokémon data and append it to the existing list.

  3. Limit Selection: Provide a dropdown menu that allows users to select the number of Pokémon to fetch per page. Options should include [1, 5, 10, 50, 100, 500].

  4. Handle Loading States: Display a loading message when data is being fetched.

  5. Handle Error States: Display an error message if the data fetch fails, along with a "Retry" button to attempt fetching the data again.

  6. Disable "Load More" Button: Disable the "Load More" button when there are no more Pokémon to fetch or when a fetch is already in progress.

Constraints

  • Do not change the overall structure of the component or the CSS classes used.
  • Do not change the data-testid attributes implemented.
  • Do not change the current error management logic of the component.

Custom Hook Details

The useFetchPokemon custom hook provides the following properties and methods:

  • Properties:

  • data: The fetched data, containing Pokémon results and pagination information.

  • isLoading: A boolean indicating if the data is currently being loaded.

  • isError: A boolean indicating if there was an error during data fetching.

  • error: The error object if isError is true.

  • isFetchingNextPage: A boolean indicating if the next page of data is being fetched.

  • hasNextPage: A boolean indicating if there is more data to fetch.

  • Methods:

  • fetchNextPage(): Function to fetch the next page of Pokémon data.

  • setLimit(newLimit): Function to set a new fetch limit.

  • refetch(): Function to retry fetching data after an error.

Hints

  • Flatten the Data: Since the data is paginated, you might need to flatten the pages to get a single list of Pokémon.
  • Event Handlers: Implement event handlers for limit change and fetching the next page.
  • Conditional Rendering: Use conditional rendering to handle loading and error states.
  • Disable Buttons Appropriately: Ensure buttons are disabled when actions cannot be performed.
import React from 'react';
import { useFetchPokemon } from './useFetchPokemon';

function PokemonList() {
  const limitOptions = [1, 5, 10, 50, 100, 500];
  const initialLimit = 10;
  const { data, isLoading, isError, error, fetchNextPage, isFetchingNextPage, hasNextPage, setLimit, refetch } = useFetchPokemon(initialLimit);

  // Handle limit change
  const handleLimitChange = (newLimit) => {
    // Implement limit change logic
  };

  // Handle fetching the next page
  const handleFetchNextPage = () => {
    // Implement fetch next page logic
  };


  return (
    <div>
      {/* Limit selection UI */}
      <div>
        <label htmlFor="limit-select">Select Fetch Limit: </label>
        <select
          id="limit-select"
          data-testid="limit-select"
          onChange={(e) => handleLimitChange(Number(e.target.value))}
          defaultValue={initialLimit}
        >
          {limitOptions.map((option) => (
            <option key={option} value={option}>
              {option}
            </option>
          ))}
        </select>
      </div>

      <button
        data-testid="load-more-button"
        onClick={handleFetchNextPage}
        // TODO: Disable button when there's no next page or when fetching
      >
        {/* TODO: Implement proper button text based on state */}
        {/* Use a condition to display:
          - "Loading more..." when isFetchingNextPage is true
          - "Load More" when hasNextPage is true and not fetching
          - "No more Pokémon" when hasNextPage is false
        */}
        Load More
      </button>

      {/* TODO: Implement loading state */}
      {/* Add a condition to check isLoading and display a loading message <p>Loading Pokémon...</p> */}

      {/* TODO: Implement error state */}
      {/* Add a condition to check isError and display an error message with a retry button */}
      {/* Retry button will use the refetch from customHook*/}

      {/* TODO: Implement Pokémon list display */}
      {/* Map through the data and display a list of Pokémon names */}
    </div>
  );
}

export default PokemonList;

Open browser consoleTests