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:
useEffect
to ensure that selected generation is always valid.filter()
to limit display to selected generation.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.