Reputation: 462
This is fetching from Pokemon API which response with an array that I want to pass useState variable initialized as empty array with setValue function.
React component is below:
import React, { useState, useEffect } from "react";
export default function Pokemones() {
const [pokemons, setPokemons] = useState([]);
useEffect(() => {
async function fetchData() {
// Call fetch
const res = await fetch("https://pokeapi.co/api/v2/pokemon/");
// Pull out the data
const json = await res.json();
// Save the data to array
console.log(json.results);
}
fetchData();
}, []);
return (
<ul>
{pokemons.map((pokemon) => (
<li>
<p>Name = {pokemon.name}</p>
<p>URL = {pokemon.name}</p>
</li>
))}
</ul>
);
}
I tried directly set setPokemons(json.results);
or by json.results.map
, received same error.
I did other tries but I got similar errors
// atfet console.log and before fetchData function
let pok = [];
json.results.map((p) => (pok = [...pok, p]));
console.log(pok);
setPokemons(pok);
}
The error received on consola is:
Uncaught Error: Objects are not valid as a React child (found: object with keys
{name, url}). If you meant to render a collection of children, use an array instead.
I guess that array is not passing to variable pokemons
but I am able to see in console the array. what part is that I am missing.
thanks
Upvotes: 0
Views: 130
Reputation: 135227
minimum example
Here's a minimum working example you can run here and verify the results in your own browser.
function App() {
const [pokemon, setPokemon] = React.useState([])
React.useEffect(_ => {
fetch("https://pokeapi.co/api/v2/pokemon/")
.then(res => res.json())
.then(res => setPokemon(res.results))
.catch(console.error)
}, [])
return <ul>
{pokemon.map(p =>
<li key={p.name}>
<a href={p.url}>{p.name}</a>
</li>
)}
</ul>
}
ReactDOM.render(<App/>, document.querySelector("#app"))
ul { list-style-type: none; padding-left: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
going further
We can expand the app's functionality a bit by making the list item's clickable and show the selected Pokémon details -
📸 pokedex app screenshot |
---|
![]() |
To do this we break the program down into three parts. First, the List
component -
function List({ pokemon, onClick }) {
return <ul id="list">
{pokemon.map(p =>
<li key={p.name} onClick={onClick(p)}>
{p.name}
</li>
)}
</ul>
}
Second, the Details
component -
function Details({ url }) {
const [data, setData] = React.useState(null)
React.useEffect(_ => {
url && fetch(url)
.then(res => res.json())
.then(res => setData(res))
.catch(console.error)
}, [url])
return data
? <pre id="details">
<h3>{data.name}</h3>
{JSON.stringify(data, null, 2)}
</pre>
: <pre id="details"><h3>Select a Pokémon in the list</h3></pre>
}
And finally the Pokedex
component which brings it all together -
function Pokedex() {
const [pokemon, setPokemon] = React.useState([])
const [selected, setSelected] = React.useState(null)
const selectPokemon = pokemon => event =>
setSelected(pokemon.url)
React.useEffect(_ => {
fetch("https://pokeapi.co/api/v2/pokemon/")
.then(res => res.json())
.then(res => setPokemon(res.results))
.catch(console.error)
}, [])
return <div id="pokedex">
<List pokemon={pokemon} onClick={selectPokemon} />
<Details url={selected} />
</div>
}
Hopefully this gives you a better idea of how React apps are put together. You can run the Pokedex
demo below -
function Pokedex() {
const [pokemon, setPokemon] = React.useState([])
const [selected, setSelected] = React.useState(null)
const selectPokemon = pokemon => event =>
setSelected(pokemon.url)
React.useEffect(_ => {
fetch("https://pokeapi.co/api/v2/pokemon/")
.then(res => res.json())
.then(res => setPokemon(res.results))
.catch(console.error)
}, [])
return <div id="pokedex">
<List pokemon={pokemon} onClick={selectPokemon} />
<Details url={selected} />
</div>
}
function List({ pokemon, onClick }) {
return <ul id="list">
{pokemon.map(p =>
<li key={p.name} onClick={onClick(p)}>
{p.name}
</li>
)}
</ul>
}
function Details({ url }) {
const [data, setData] = React.useState(null)
React.useEffect(_ => {
url && fetch(url)
.then(res => res.json())
.then(res => setData(res))
.catch(console.error)
}, [url])
return data
? <pre id="details">
<h3>{data.name}</h3>
{JSON.stringify(data, null, 2)}
</pre>
: <pre id="details"><h3>Select a Pokémon in the list</h3></pre>
}
ReactDOM.render(<Pokedex/>, document.querySelector("#app"))
body, ul, pre { margin: 0; padding: 0; }
ul { list-style-type: none; }
li { cursor: pointer; }
#pokedex { display: flex; }
#list { margin-right: 2rem; }
#details { flex-grow: 1; background-color: #ffc; max-height: 100vh; overflow-y: scroll; padding-left: 1rem; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
Upvotes: 1
Reputation: 501
I hope this helps.
import React, { useState, useEffect } from "react";
export default function Pokemones() {
const [pokemons, setPokemons] = useState([]);
useEffect(() => {
async function fetchData() {
// Call fetch
const res = await fetch("https://pokeapi.co/api/v2/pokemon/");
// Pull out the data
const json = await res.json();
// Save the data to array
console.log(json.results);
setPokemons(json.results);
}
fetchData();
}, []);
return (
<ul>
{pokemons.map((pokemon, index) => {
return <li key={index}>
<p>Name = {pokemon.name}</p>
<p>URL = {pokemon.name}</p>
</li>
})}
</ul>
);
}
Upvotes: 2