【问题标题】:reactjs state is not being updated with button click using useState hookreactjs 状态没有通过使用 useState 钩子单击按钮来更新
【发布时间】:2021-08-10 02:31:33
【问题描述】:

我是 React js 的新手,为了练习我的技能,我尝试使用 pokemon api 制作一个 pokemon react js 应用程序。在学习完教程后,我决定在应用程序中添加更多功能以供进一步练习。

我想要做的是使用useState 钩子和onClick 函数在单击按钮时更改获取的url。当我将resourceType 从pokemon 更改为berry 时,它更新成功,但是问题是当我尝试从berry 查询pokemon 时,状态未更新为pokemon。

我不确定为什么会发生这种情况,因为在 useEffect 函数中,我已将依赖项包含为 resourceType,因此每次更新 resourceType 时它都应该更改。

任何正确方向的提示将不胜感激。

主App.js组件:

import './App.css';
import { Button } from '@material-ui/core'
import React, { useEffect, useState } from 'react'
import BerryCards from './Components/BerryCards';
import PokemonCards from './Components/PokemonCards';

function App() {
  const [resourceType, setResourceType] = useState('pokemon');
  const [data, setData] = useState([]);
  const [nextUrl, setNextUrl] = useState('');
  const [prevUrl, setPrevUrl] = useState('');
  const [loading, setLoading] = useState(true);

  async function getAllPokemon(url) {
    return new Promise((resolve, reject) => {
      fetch(url)
        .then(res => res.json())
        .then(data => {
          resolve(data);
        })
    })
  }

  async function getPokemons(url) {
    return new Promise((resolve, reject) => {
      fetch(url)
        .then(res => res.json())
        .then(data => {
          resolve(data);
        })
    })
  }

  useEffect(() => {
    async function fetchData() {
      try {
        let response = await getAllPokemon(`https://pokeapi.co/api/v2/${resourceType}`);
        setNextUrl(response.next)
        setPrevUrl(response.previous)
        setLoading(false)
        await loadingPokemon(response.results);
      }
      catch (e) {
        console.log(e);
      }
    }
    fetchData();
  }, [resourceType])

  console.log(resourceType)

  const next = async () => {
    setLoading(true)
    let nextData = await getAllPokemon(nextUrl)
    await loadingPokemon(nextData.results)
    setNextUrl(nextData.next)
    setPrevUrl(nextData.previous)
    setLoading(false)
  }


  const prev = async () => {
    if (!prevUrl) {
      return;
    } else {
      setLoading(true)
      let nextData = await getAllPokemon(prevUrl)
      await loadingPokemon(nextData.results)
      setNextUrl(nextData.next)
      setPrevUrl(nextData.previous)
      setLoading(false)
    }

  }

  const loadingPokemon = async (pokemonData) => {
    let _pokemon = await Promise.all(pokemonData.map(async pokemon => {
      let pokemonRecord = await getPokemons(pokemon.url);
      return pokemonRecord;
    }))

    setData(_pokemon)
  }

  return (
    <div>
      {loading ? <h1>Loading...</h1> : (
        <>
          <div>
            <div>
              <Button onClick={() => setResourceType('berry')}>Berries</Button>
              <Button onClick={() => setResourceType('pokemon')}>Pokemon</Button>
            </div>

            <div>
              {!prevUrl ? <Button onClick={prev} variant="outlined" disabled>Prev</Button> :
                <Button onClick={prev} variant="outlined" color="primary">Prev</Button>}
              {!nextUrl ? <Button onClick={next} disabled variant="outlined">Next</Button> :
                <Button onClick={next} color="primary" variant="outlined">Next</Button>}
            </div>
            {resourceType === 'pokemon' ? data && data.map((pokemon, i) => {
              return (
                <div>
                  <PokemonCards key={i}
                    pokemon={pokemon} />
                </div>
              )
            }) : data && data.map((berry, i) => {
              return (
                <div>
                  <BerryCards key={i}
                    berry={berry} />
                </div>
              )

            })}

          </div >
        </>
      )
      }

    </div >
  )
}

export default App;

使用 props 将数据传递给其他 UI 组件

import React from 'react'
import { Card } from '@material-ui/core'

    const BerryCards = ({ berry }) => {
        return (
            <div>
                <Card>
                    <p>{berry.name}</p>
                    <p>{berry.natural_gift_power}</p>
                </Card>
            </div>
        )
    }
    export default BerryCards

    import React from 'react'
    import { Card } from '@material-ui/core'
    const PokemonCards = ({ pokemon }) => {
        try {
            return (
                <div>
                    <Card>
                        <p>{pokemon.name}</p>
                        {pokemon.types.map(type => <p key={Math.random() + 1}>{type.type.name}</p>)}
                        <p>Height {pokemon.height}</p>
                        <p>Weight {pokemon.weight}</p>
                        <p>Ability: {pokemon.abilities[0].ability.name}</p>
                        <img src={pokemon.sprites.front_default} alt={pokemon.name}></img>
                    </Card>
                </div>
            )
        } catch (e) {
            console.log(e)
            //the problem- when request url is changed to berries, it remains as berries and is not changed
            console.log(pokemon)
        }
    
    }
    export default PokemonCards

【问题讨论】:

  • >但是问题是当我尝试从berry 查询pokemon 你的意思是当你点击pokemon 按钮时?
  • @CVerica 是的,很抱歉没有澄清 - 所以最初当状态为“口袋妖怪”时,它成功地从查询中加载数据,但是当我点击 berry 后点击口袋妖怪按钮时,状态不会'不改变并保持为'浆果'

标签: javascript reactjs use-state


【解决方案1】:

您当前的代码抛出错误,因为您没有返回任何要渲染的元素。只需在 catch 语句中添加以下代码

  } catch (e) {
      return null;
  }

您还可以完全删除 try &amp; catch 并在您的代码中添加空检查,如下所示:

const PokemonCards = ({ pokemon }) => {
      return (
          <div>
              <Card>
                  <p>{pokemon.name}</p>
                  {pokemon.types && pokemon.types.map(type => <p key={Math.random() + 1}>{type.type.name}</p>)}
                  <p>Height {pokemon.height}</p>
                  <p>Weight {pokemon.weight}</p>
                  <p>Ability: {pokemon.abilities && pokemon.abilities[0].ability.name}</p>
                  <img src={pokemon.sprites && pokemon.sprites.front_default} alt={pokemon.name}></img>
              </Card>
          </div>
      )
}

【讨论】:

    猜你喜欢
    • 2019-09-06
    • 1970-01-01
    • 1970-01-01
    • 2020-08-20
    • 1970-01-01
    • 2021-04-17
    • 1970-01-01
    • 2020-04-19
    • 1970-01-01
    相关资源
    最近更新 更多