简体   繁体   中英

How to make filter with Radio Input

i'm actually learning Javascript and React but i have a problem. I'm trying to build a Pokedex but i have a problem.

i put some Radio Input to make a filter of generation (pokemon) but i don't know how to link my inputs with the apiGeneration number on the API...

i also want to make a search bar by name, i'm able to see the searchBar.value on a console.log(), but i can't put an addeventlistener on the searchBar element...

Thanks a lot for your help. ^^ API link: https://pokebuildapi.fr/api/v1/pokemon

import axios from "axios";
import React, { useEffect, useState } from "react";
import Card from "./Card";

const Pokedex = () => {
  const [data, setData] = useState([]);
  const radios = ["1G", "2G", "3G", "4G", "5G", "6G", "7G", "8G"];
  const [selectedRadio, setSelectedRadio] = useState("");

  useEffect(() => {
    axios
      .get("https://pokebuildapi.fr/api/v1/pokemon")
      .then((res) => setData(res.data));
  }, []);
  return (
    <div className="pokemons">
      <h2 id="search-title">Pokedex</h2>
      <p className="search-text">Recherhe par nom</p>
      <div>
        <input type="search" id="search-bar"></input>
      </div>

      <div className="gen-search">
        {radios.map((generation) => (
          <ul className="radio-container">
            <li>
              <input
                type="radio"
                id={generation}
                name="generationRadio"
                checked={generation === selectedRadio}
                onChange={(e) => setSelectedRadio(e.target.id)}
              />
              <label htmlFor={generation}>{generation}</label>
            </li>
          </ul>
        ))}
      </div>
      {selectedRadio && (
        <button onClick={() => setSelectedRadio("")}>
          Annuler la recherche
        </button>
      )}
      <div className="pokemon-container">
        <ul>
          {data
            .filter((pokemon) => {
              /* ... */
            })
            .map((pokemon, index) => (
              <Card key={index} pokemon={pokemon} />
            ))}
        </ul>
      </div>
    </div>
  );
};

export default Pokedex;

API

// 20230130034321
// https://pokebuildapi.fr/api/v1/pokemon

[
  {
    "id": 1,
    "pokedexId": 1,
    "name": "Bulbizarre",
    "image": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/1.png",
    "sprite": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/1.png",
    "slug": "Bulbizarre",
    "stats": {
      "HP": 45,
      "attack": 49,
      "defense": 49,
      "special_attack": 65,
      "special_defense": 65,
      "speed": 45
    },
    "apiTypes": [
      {
        "name": "Poison",
        "image": "https://static.wikia.nocookie.net/pokemongo/images/0/05/Poison.png"
      },
      {
        "name": "Plante",
        "image": "https://static.wikia.nocookie.net/pokemongo/images/c/c5/Grass.png"
      }
    ],
    "apiGeneration": 1,

Here is an example based off your snippet.

Changes:

  • Calculate list of generations from the loaded pokemon data.
  • Store selected generation as numeric value provided by API.
  • Added useEffect to ensure that selected generation is always valid.
  • Added filter() to limit display to selected generation.
  • Updated key to use pokemon.id , this is a better value as it will require react to do less work if you reorder or change the list at any point in time.
import axios from "axios";
import React, { useEffect, useState, useMemo } from "react";
import Card from "./Card";

const Pokedex = () => {
    const [data, setData] = useState([]);

    // Get a list of generations from the data retrieved from the all pokemon api.
    const generations = useMemo(() => {
        // if data not yet loaded, return empty array (no generations).
        if (!data) {
            return [];
        }

        // get a list of all unique generations:
        //    - use list.map() to get the apiGeneration property of each pokemon.
        //    - use new Set(list) to restrict the list to only unique values.
        //    - use [...list] to change the Set back into an array.
        const allGenerations = [...new Set(data.map(x => x.apiGeneration))];

        // sort the list
        allGenerations.sort();

        // return the list of all generations.
        return allGenerations;
    }, [data])

    // state value to store the currently selected generation.
    const [selectedGeneration, setSelectedGeneration] = useState(undefined);

    // When ever the list of generations changes (should only be on reload of
    // pokemon data) ensure that the selected generation still exists, otherwise
    // set it back to all generations (undefined).
    useEffect(() => {
        setSelectedGeneration(c => {
            if (!!c && !generations.includes(c)) {
                return undefined;
            }

            return c;
        });
    }, [generations, setSelectedGeneration])

    // load pokemon data.
    useEffect(() => {
        axios
            .get("https://pokebuildapi.fr/api/v1/pokemon")
            .then((res) => setData(res.data));
    }, []);


    return (
        <div className="pokemons">
            <h2 id="search-title">Pokedex</h2>
            <p className="search-text">Recherhe par nom</p>
            <div>
                <input type="search" id="search-bar"></input>
            </div>

            <div className="gen-search">
                {
                    // loop through generations and create radio buttons
                    generations?.map((generation) => (
                        <ul className="radio-container">
                            <li>
                                <input
                                    type="radio"
                                    id={`generation-${generation}`}
                                    name="generationRadio"
                                    checked={generation === selectedGeneration}
                                    onChange={(e) => setSelectedGeneration(generation)}
                                />
                                <label htmlFor={`generation-${generation}`}>G{generation}</label>
                            </li>
                        </ul>
                    ))
                }
            </div>
            {
                // create button to clear generation filter.
                selectedGeneration && (
                    <button onClick={() => setSelectedGeneration(undefined)}>
                        Annuler la recherche
                    </button>
                )
            }
            <div className="pokemon-container">
                <ul>
                    {
                        // filter and map out pokemon.
                        data
                            .filter((pokemon) => {
                                // if no filter, return all pokemon.
                                if (!selectedGeneration) {
                                    return true;
                                }

                                // ensure pokemon matches selected generation.
                                return pokemon.apiGeneration === selectedGeneration;
                            })
                            .map((pokemon, index) => (
                                <Card key={pokemon.id} pokemon={pokemon} />
                            ))
                    }
                </ul>
            </div>
        </div>
    );
};

export default Pokedex;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM