skip to Main Content

I’m trying to create an pokedex app. In my app.js, I use an useEffect to make an API call then I use a child component to detail each card.
What I’m trying to do is when an user click on a card, app.js retrieve the selected pokemon’s data which later will be used to open Modal and show the selected pokemon’s infos.
On app.js, I create a props handleClickparent which is a function to console.log my data from PokemonCard compenent.

On app.js :

import "./App.css";
import "bootstrap/dist/css/bootstrap.min.css";
import React, { useState, useEffect } from "react";
import PokemonCard from "./component/PokemonCard";

function App() {
  const [pokemonList, setPokemonList] = useState([]);
  const [findPokemon, setFindPokemon] = useState("");
  const [pokemonInfos, setPokemonInfos] = useState(null);

  //Function for API Call
  const searchPokemon = async () => {
    const rawData = await fetch("https://pokeapi.co/api/v2/pokemon?limit=150");
    const data1 = await rawData.json();
    const data2 = await Promise.all(
      data1.results.map((data) =>
        fetch(`https://pokeapi.co/api/v2/pokemon/${data.name}`).then((data) =>
          data.json()
        )
      )
    );
    setPokemonList(data2);
  };
  //Console.log data from PokemonCard component
  const getData = (pokemon) => {
    return console.log(pokemon);
  };

  //Initialize component
  useEffect(() => {
    searchPokemon();
  }, []);


  return (
    <div>
      <h5 className="title">Pokedex</h5>
      <div className="SearchBar">
        <input
          className="Input"
          type="search"
          placeholder="...Search Pokemon"
          onChange={(e) => setFindPokemon(e.target.value)}
          value={findPokemon}
        ></input>
      </div>
      <PokemonCard
        pokemonList={pokemonList}
        searchValue={findPokemon}
        handleClickParent={getData}
      />
    </div>
  );
}
export default App;

PokemonCard component

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

function PokemonCard({ pokemonList, searchValue }, props) {
  //using Hook to change the value when the user is hovering or selecting on a card
  const [IsHovering, setIsHovering] = useState(-1);
  const [selectIndex, setSelectIndex] = useState(-1);

//On click I send the select pokemon infos to the parent component
  const handleClick = (pokemon) => {
    console.log(pokemon);
    props.handleClickParent(pokemon);
  };

  return (
    <div className="RowCard">
      {pokemonList
        .filter((pokemon) => {
          return pokemon.name.match(searchValue);
        })
        .map((pokemon, i) => {
          return (
            <div
              key={i}
              className={`Card ${IsHovering === i ? "HoveringCard" : ""}`}
              onMouseEnter={() => setIsHovering(i)}
              onMouseLeave={() => setIsHovering(-1)}
              onClick={() => handleClick(pokemon)}
            >
              <p>{pokemon.name}</p>
              <img
                className="ImgPokemon"
                src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/${pokemon.id}.png`}
              ></img>
            </div>
          );
        })}
    </div>
  );
}

export default PokemonCard;

However an error is shown on my console :

PokemonCard.js:13 Uncaught TypeError: props.handleClickParent is not a function
    at handleClick (PokemonCard.js:13:1)
    at onClick (PokemonCard.js:29:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
    at invokeGuardedCallback (react-dom.development.js:4277:1)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4291:1)
    at executeDispatch (react-dom.development.js:9041:1)
    at processDispatchQueueItemsInOrder (react-dom.development.js:9073:1)
    at processDispatchQueue (react-dom.development.js:9086:1)
    at dispatchEventsForPlugins (react-dom.development.js:9097:1)
h

If anyone sees what’s wrong with my code, I would be more than happy if you would share your idea.
Thanks in advance

2

Answers


  1. You are destructuring pokemonList and searchValue, but adding a props as a second parameter of your component. Either destructure your handleClickParent or only use props and props.pokemonList (or other props) to acces your props. There is usually no second parameter in a function component, unless you are using something like forwardRef which will add the ref as second argument.

    function PokemonCard({ pokemonList, searchValue, handleCickParent }) {...}

    or

    function PokemonCard(props) {...}

    Login or Signup to reply.
  2. The issue seems to be with the way you are passing the handleClickParent function to the PokemonCard component. In the App.js file, you are passing the function as a prop named handleClickParent, but in the PokemonCard.js file, you are trying to access it as props.handleClickParent.

    you should replace this line:

    function PokemonCard({ pokemonList, searchValue }, props)
    

    with this:

    function PokemonCard({ pokemonList, searchValue, ...props })
    

    using the "rest" operator (…props) will collect any additional props passed to the component and store them in an object called props, which can be used within the component body as needed.

    or you can remove the props argument from the PokemonCard function definition, and simply use handleClickParent directly:

    function PokemonCard({ pokemonList, searchValue, handleClickParent }) {
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search