[英]Change component state - REACT
我目前正在使用 Pokemon API 開展一個項目,但我遇到了一個問題。 我想更改異步函數 getPokemonTypes() 中的 value 參數,但我在 handleSelect() 中收到的值不起作用。 在 console.log(value) 上,每次我選擇不同的選項時,值都會發生變化。 有人可以告訴我我做錯了什么嗎?
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>
);
}
您需要將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
請記住,此代碼存在一些問題,因為如果發生這種情況,您最終可能會看到與 URL 中的類型不匹配的類型的數據:
fire
並getPokemonTypes('fire')
。ice
並getPokemonTypes('ice')
。getPokemonTypes('ice')
完成加載並執行fetchData
函數的其余部分。getPokemonTypes('fire')
完成加載並執行fetchData
函數的其余部分。ice
但查看來自fire
的數據。正確的方法是這樣的:
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]);
此外,您在這里有一個錯誤:
const data = pokemonIdText.map(async (pokemonId) => {
return (
await getPokemonInfo(pokemonId)
);
});
const pokemonIdNumber = await Promise.all(data);
您想將所有這些 Promise 存儲在data
數組中,並與下面的Promise.all
一起等待它們,但您卻是一個接一個地等待它們。 它應該是這樣的:
const data = pokemonIdText.map((pokemonId) => {
return getPokemonInfo(pokemonId);
});
const pokemonIdNumber = await Promise.all(data);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.