[英]Change component state - REACT
I'm currently working on a project with the Pokemon API and i'm facing a problem.我目前正在使用 Pokemon API 开展一个项目,但我遇到了一个问题。 I want to change the value parameter in the async function getPokemonTypes(), but the value I receive in handleSelect() is not working.
我想更改异步函数 getPokemonTypes() 中的 value 参数,但我在 handleSelect() 中收到的值不起作用。 On the console.log(value), the value changes every time I select a different option.
在 console.log(value) 上,每次我选择不同的选项时,值都会发生变化。 Could someone tell me what I'm doing wrong?
有人可以告诉我我做错了什么吗?
import React from 'react'
import { useState, useEffect } from "react";
import { Link } from 'react-router-dom'
async function getPokemonTypes(value) {
const response = await fetch(`https://pokeapi.co/api/v2/type/${value}`)
const data = await response.json()
console.log(data)
return data
}
async function getPokemonInfo(pokemonId) {
const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonId}`)
const data = await response.json()
return data
}
export const PokemonTypesCard = () => {
const [pokemonTypesCard, setPokemonTypesCard] = useState({})
const [pokemonIdNumber, setPokemonIdNumber] = useState([])
const [value, setValue] = useState('normal')
const handleSelect = (value) => {
setValue(value)
}
console.log(value)
useEffect(() => {
async function fetchData() {
const pokemonTypesCard = await getPokemonTypes(value)
const pokemonIdText = pokemonTypesCard.pokemon.map((item) => {
return item.pokemon.name
})
const data = pokemonIdText.map(async (pokemonId) => {
return (
await getPokemonInfo(pokemonId)
)
})
const pokemonIdNumber = await Promise.all(data)
setPokemonIdNumber(pokemonIdNumber)
setPokemonTypesCard(pokemonTypesCard)
}
fetchData()
}, [])
return (
<section>
<div>
<label htmlFor='pokemon-types'>Choose a pokemon type</label>
<form>
<select onChange={(event) => handleSelect(event.target.value)}
value={value}>
<option value='normal'>Normal</option>
<option value='fighting'>Fighting</option>
<option value='flying'>Flying</option>
<option value='poison'>Poison</option>
<option value='ground'>Ground</option>
<option value='rock'>Rock</option>
<option value='bug'>Bug</option>
<option value='ghost'>Ghost</option>
<option value='steel'>Steel</option>
<option value='fire'>Fire</option>
<option value='water'>Water</option>
<option value='grass'>Grass</option>
<option value='electric'>Electric</option>
<option value='psychic'>Psychic</option>
<option value='ice'>Ice</option>
<option value='dragon'>Dragon</option>
<option value='dark'>Dark</option>
<option value='fairy'>Fairy</option>
<option value='shadow'>Shadow</option>
</select>
</form>
</div>
{<div>
<ul>
{!pokemonIdNumber ? '' : pokemonIdNumber.map((item, index) =>
<li key={index}>
<Link to={`/pokemon/${item.id}`}>
<img
src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${item.id}.png`}
alt={item.name}
/>
</Link>
<p>{item.name}</p>
</li>
)}
</ul>
</div>}
</section>
);
}
You need to add type
to the dependnecies array of useEffect
:您需要将
type
添加到useEffect
的依赖项数组中:
useEffect(() => {
async function fetchData() {
const pokemonTypesCard = await getPokemonTypes(value);
const pokemonIdText = pokemonTypesCard.pokemon.map((item); => {
return item.pokemon.name;
});
const data = pokemonIdText.map(async (pokemonId) => {
return (
await getPokemonInfo(pokemonId)
);
});
const pokemonIdNumber = await Promise.all(data);
setPokemonIdNumber(pokemonIdNumber);
setPokemonTypesCard(pokemonTypesCard);
}
fetchData();
}, [value]); // <= HERE
Keep in mind this code has some issues, as you might end up seeing data for a type that doesn't match the one in the URL if something like this happens:请记住,此代码存在一些问题,因为如果发生这种情况,您最终可能会看到与 URL 中的类型不匹配的类型的数据:
fire
and getPokemonTypes('fire')
is called.fire
并getPokemonTypes('fire')
。ice
and getPokemonTypes('ice')
is called.ice
并getPokemonTypes('ice')
。getPokemonTypes('ice')
finishes loading and the rest of the fetchData
function executes. getPokemonTypes('ice')
完成加载并执行fetchData
函数的其余部分。getPokemonTypes('fire')
finishes loading and the rest of the fetchData
function executes. getPokemonTypes('fire')
完成加载并执行fetchData
函数的其余部分。ice
but see data from fire
.ice
但查看来自fire
的数据。 The proper way to do it would be like this:正确的方法是这样的:
useEffect(() => {
let shouldUpdate = true;
async function fetchData() {
const pokemonTypesCard = await getPokemonTypes(value);
if (!shouldUpdate) return;
const pokemonIdText = pokemonTypesCard.pokemon.map((item) => {
return item.pokemon.name;
});
const data = pokemonIdText.map((pokemonId) => {
return getPokemonInfo(pokemonId);
});
const pokemonIdNumber = await Promise.all(data);
if (!shouldUpdate) return;
setPokemonIdNumber(pokemonIdNumber);
setPokemonTypesCard(pokemonTypesCard);
}
fetchData();
// This cleanup function will be called if the `useEffect`'s
// dependencies change, so if you run it twice in a row for
// different types, when the result of the first one arrives,
// it will be discarded:
return () => {
shouldUpdate = false;
};
}, [value]);
Also, you have an error here:此外,您在这里有一个错误:
const data = pokemonIdText.map(async (pokemonId) => {
return (
await getPokemonInfo(pokemonId)
);
});
const pokemonIdNumber = await Promise.all(data);
You want to store all those promises in the data
array and await them all together with Promise.all
below, but you are instead awaiting them one by one.您想将所有这些 Promise 存储在
data
数组中,并与下面的Promise.all
一起等待它们,但您却是一个接一个地等待它们。 It should be like this:它应该是这样的:
const data = pokemonIdText.map((pokemonId) => {
return getPokemonInfo(pokemonId);
});
const pokemonIdNumber = await Promise.all(data);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.