Estoy obteniendo datos de una API que devuelve una matriz de objetos en este formato.
{Name: 'hitmonchan', Description: 'Fighting-type Pokémon introduced in Generation I'} {Name: 'Gogoat', Description: 'A quadrupedal, hooved Pokémon similar to a goat'}... and so on Esto es lo que estoy tratando de hacer. Busco todos los Pokémon que tienen más de 500, los coloco en una matriz llamada allPokemons . Luego quiero hacer cosas con 4 pokemons al azar de la lista. Así que tendré una matriz llamada smallRandomPokemonArray con solo cuatro pokemons elegidos al azar de la matriz allPokemon .
import { useEffect, useState } from 'react'; import { getallPokemons } from '../services/pokemonapi'; const empty_pokemon = { 'Name': '', 'Description': '' } function PokemonComponent() { const [allPokemons, setAllPokemons] = useState([]); const [smallRandomPokemonArray, setSmallRandomPokemonArray] = useState([]); useEffect(() => { getAll(); }, []); const getAll = () => { getallPokemons() .then(data => { //actual data with over 500 objects show in log console.log(data); setAllPokemons(data); randomChooser(data.length) }) } const randomChooser = (length) => { let temporaryArray = []; for (let i = 0; i < 4; i++) { const randomIndex = Math.floor(Math.random() * length); //First Problem: this is returning index in numbers followed by undefined... why? console.log(randomIndex + " " + allPokemons[randomIndex]); temporaryArray.push(allPokemons[randomIndex]); //Second Problem: this is also returning "temp undefined" console.log("temp " + temporaryArray[i]); } setSmallRandomPokemonArray(temporaryArray); } return ( <> <div className="pokemondiv"> { smallRandomPokemonArray.map((element) => ( <div> <p>{element.Name}</p> <p>{element.Description}</p> </div> )) } </div> </> ) } export default PokemonComponent; Cuando intento imprimir valores de setSmallRandomPokemonArray , aparece ese error:
Uncaught TypeError: Cannot read properties of undefined (reading 'Name') Además, mire el First problem and Second problem en el código. También aparecen como indefinidos en el archivo console.log. Según tengo entendido, debería funcionar porque allPokemons ya existen cuando empiezo a aleatorizarlo. Luego simplemente inserto cuatro valores aleatorios en smallRandomPokemonArray . No sé por qué está arrojando el error.
Estás llamando a randomChooser(data.length) justo después de setAllPokemons(data); en getAll . En este punto, allPokemons que se usa dentro randomChooser sigue siendo [] .
matrizvacia[0] = indefinido. undefined.Name = No se pueden leer las propiedades de undefined. La conclusión es que cuando llamas a
setState, elstaterelacionado se actualiza de forma asíncrona. Se necesita volver a renderizar para tener el valor actualizado.
Cambie getAll al código a continuación, por lo que su único trabajo es completar el estado de todos los allPokemons :
const getAll = () => { getallPokemons().then((data) => { setAllPokemons(data); }); }; Usa un useEffect para obtener los cuatro pokemons que necesitas:
useEffect(() => { /* I moved randomChooser here, so you don't have to put it in useEffect's dependencies array, which if you do, you should wrap randomChooser in a useCalback, as otherwise you get an infinite call. */ const randomChooser = (length) => { const temporaryArray = []; for (let i = 0; i < 4; i++) { const randomIndex = Math.floor(Math.random() * length); temporaryArray.push(allPokemons[randomIndex]); } setSmallRandomPokemonArray(temporaryArray); }; if (allPokemons.length <= 0) return; randomChooser(allPokemons.length); }, [allPokemons]); Cambie randomChooser para que reciba la matriz, no su longitud:
const randomChooser = (allPokemons) => { let temporaryArray = []; for (let i = 0; i < 4; i++) { const randomIndex = Math.floor(Math.random() * allPokemons.length); temporaryArray.push(allPokemons[randomIndex]); } setSmallRandomPokemonArray(temporaryArray); }; Cambia getAll para que le des datos a randomChooser :
const getAll = () => { getallPokemons().then((data) => { setAllPokemons(data); randomChooser(data); }); };allPokemons no se ha establecido en el punto en el que lo está utilizando en randomChooser . react establecerá todos los estados después de que la función termine de ejecutarse. Debe pasar los datos a randomChooser .
const randomChooser = (data) => { const length = data.length let temporaryArray = []; for (let i = 0; i < 4; i++) { const randomIndex = Math.floor(Math.random() * length); //First Problem: this is returning index in numbers followed by undefined... why? console.log(randomIndex + " " + data[randomIndex]); temporaryArray.push(data[randomIndex]); //Second Problem: this is also returning "temp undefined" console.log("temp " + temporaryArray[i]); } setSmallRandomPokemonArray(temporaryArray); }