skip to Main Content

I am learning React hooks and made a project to display a random Pokemon name through https://pokeapi.co/docs/v2#pokemon by calling a random Pokemon ID. I’m not quite sure how to trigger the useEffect to fetch after clicking on the button.

import './App.css';
import { useState, useEffect } from 'react';


  function getNewPokemonId(pokemon){
  pokemon =  Math.floor(Math.random() * 1011);
  console.log(pokemon)
  return pokemon;
}

function App() {
  const [pokemon , setNewPokemon] = useState(1);


  useEffect(() => {
    console.log("render");
    const pokemonID = getNewPokemonId()
    fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonID}`)
    .then((response) => response.json())
    .then((json) =>
      setNewPokemon(json)
  );
  
  }, []);


  return (
    <main>
      <h1>
        Random Pokemon Generator
      </h1>
      <section>
        <button onClick={() => setNewPokemon(getNewPokemonId(pokemon))}>
          New Pokemon
        </button>
        <h3>{pokemon?.name}</h3>
      </section>

    </main>
  );
}

export default App;

After clicking on the button I don’t get a new Pokemon name instead it is blank.

4

Answers


  1. having [] at the end of the useEffect will mean it will only trigger once at the start of the page load.
    having this: [pokemon] will make the useEffect run every time the variable changes.

    Login or Signup to reply.
  2. You can define a function to fetch the data for a Pokemon by id and call it on mount and in the click event handler.

    function App() {
      const [pokemon, setNewPokemon] = useState();
      const getPokemon = id => fetch(`https://pokeapi.co/api/v2/pokemon/${id}`).then(res => res.json()).then(d => setNewPokemon(d));
      useEffect(() => {
        console.log("render");
        getPokemon(getNewPokemonId());
      }, []);
    
      return (
        <main>
          <h1>Random Pokemon Generator</h1>
          <section>
            <button onClick={() => getPokemon(getNewPokemonId())}>
              New Pokemon
            </button>
            <h3>{pokemon?.name}</h3>
          </section>
        </main>
      );
    }
    
    Login or Signup to reply.
  3. I created a sandbox with this app working:

    Sandbox https://codesandbox.io/s/holy-morning-tkwtpv

    import "./styles.css";
    import { useState, useEffect } from "react";
    
    function getNewPokemonId() {
      const pokemon = Math.floor(Math.random() * 1011);
      console.log(pokemon);
      return pokemon;
    }
    
    export default function App() {
      const [pokemon, setNewPokemon] = useState(1);
    
      const fetchPokemon = async () => {
        const response = await fetch(
          `https://pokeapi.co/api/v2/pokemon/${getNewPokemonId()}`
        );
        const data = await response.json();
        setNewPokemon(data);
      };
    
      useEffect(() => {
        fetchPokemon();
      }, []);
    
      const handleOnClick = () => {
        fetchPokemon();
      };
    
      return (
        <div className="App">
          <h1>Random Pokemon Generator</h1>
          <section>
            <button onClick={handleOnClick}>New Pokemon</button>
            <h3>{pokemon?.name}</h3>
          </section>
        </div>
      );
    }
    
    

    I hope that this could help

    Login or Signup to reply.
  4. It’ not fool-proof, but it’s a start. You should store the Pokémon data into the state, not the ID. Make sure you properly set the state as well.

    Note

    If you notice, the IDs jump from 1010 to 10001.

    So the random range should technically be: 1-1010, 10001-10271.


    Example

    Here is an basic working example of a Pokémon randomizer. It’s fairly responsive.

    const { useCallback, useEffect, useState } = React;
    
    // Better PRNG than Math.random
    // Source: https://stackoverflow.com/a/47593316/1762224
    const mulberry32 = (seed) =>
      () => {
        let t = seed += 0x6D2B79F5;
        t = Math.imul(t ^ t >>> 15, t | 1);
        t ^= t + Math.imul(t ^ t >>> 7, t | 61);
        return ((t ^ t >>> 14) >>> 0) / 4294967296;
      }
    
    const rand = mulberry32(performance.now()); // Seeded with current time
    
    const randomInt = (min, max) => Math.floor(rand() * (max - min + 1)) + min;
    
    const toTitleCase = (str = '') =>
      str.replace(/wS*/g, (txt) =>
        txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase());
    
    // Refer to: https://pokeapi.co/api/v2/pokemon?offset=0&limit=2000
    const ranges = [[1, 1010], [10001, 10271]]; // Distribution: (1010, 271)
    
    const getRandomId = () => {
      const which = randomInt(1, 5);
      const range = ranges[which === 5 ? 1 : 0]; // 20% for range #2
      return randomInt(...range);
    };
    
    const apiBaseUrl = 'https://pokeapi.co/api/v2';
    
    const App = () => {
      const [pokemonData, setPokemonData] = useState({ id: 0, name: '', sprites: [] });
      const [loading, setLoading] = useState(false);
      const [errorText, setErrorText] = useState('');
      
      const randomize = useCallback(() => {
        setErrorText('');
        setLoading(true);
        const randId = getRandomId();
        fetch(`${apiBaseUrl}/pokemon/${randId}`)
          .then(res => res.json())
          .then(data => {
            setPokemonData(data);
          })
          .catch(() => {
            setErrorText(`Pokemon with ID of ${randId} not found!`);
          })
          .finally(() => setLoading(false));
      }, []);
      
      useEffect(() => {
        randomize();
      }, []);
      
      return (
        <main>
          <h1>Random Pokemon Generator</h1>
          <section>
            <button disabled={loading} onClick={randomize}>New Pokemon</button>
            {errorText !== '' && <p style={{color:'red'}}>{errorText}</p>}
            <h3>[{pokemonData.id}] {toTitleCase(pokemonData.name)}</h3>
            <img src={pokemonData.sprites.front_default} />
          </section>
        </main>
      );
    };
    
    ReactDOM.createRoot(document.getElementById("root")).render(<App />);
    <div id="root"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search