簡體   English   中英

更改組件狀態 - REACT

[英]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 中的類型不匹配的類型的數據:

  • 您選擇firegetPokemonTypes('fire')
  • 您選擇icegetPokemonTypes('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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM