'How to modify react button "More"?

I have the following React component:

import React from "react";
import { useState, useEffect } from "react";
import { TailSpin } from "react-loader-spinner";

function Pokemon({ name, url }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch(url)
      .then((r) => r.json())
      .then(setData);
  }, [url]);

  const onClickButtonChange = () => {
    let cardMore = document.querySelector(".card_more");
    let cardMain = document.querySelector(".card_main");

    cardMore.style.display = "block";
    cardMain.style.display = "none";
  };

  return (
    <div>
      {data ? (
        <div>
          <div className="card card_main">
            <div className="animate__animated animate__bounceInUp">
              <div className="card-image">
                <img src={data.sprites.front_default} alt="pokemon_img" />
                <span className="card-title">{name}</span>
                <button onClick={onClickButtonChange}>More</button>
              </div>
              <div className="card-content">
                {data.abilities.map((n, index) => (
                  <p key={index}>{n.ability.name}</p>
                ))}
              </div>
            </div>
          </div>
          <div className="card card_more">
            <p>{data.height}</p>
            <p>{data.weight}</p>
          </div>
        </div>
      ) : (
        <div>
          <TailSpin type="Puff" color="purple" height={100} width={100} />
        </div>
      )}
    </div>
  );
}

export { Pokemon };

My implementation of the More button needs to display additional features (the card_more block). Right now this function only works on the very first element. I understand that in React this can most likely be done more correctly, but I don’t know how, so I use CSS styles.

P.S Edited:

I tried to use React features, maybe someone can tell me or does it make sense?

import React from "react";
import { useState, useEffect } from "react";
import { TailSpin } from "react-loader-spinner";

function Pokemon({ name, url }) {
  const [data, setData] = useState(null);
  const [show, setShow] = useState(false);

  useEffect(() => {
    fetch(url)
      .then((r) => r.json())
      .then(setData);
  }, [url]);


  const handleMore = async () => {
    if (show === true) {
      setShow(false);
    } else if (show === false || !data) {
      const r = await fetch(url);
      const newData = await r.json();
      setData(newData);
      setShow(true);
    }
  };

  return (
    <div>
      {data && show ? (
        <div>
          <div className="card card_main">
            <div className="animate__animated animate__bounceInUp">
              <div className="card-image">
                <img src={data.sprites.front_default} alt="pokemon_img" />
                <span className="card-title">{name}</span>
              </div>
              <div className="card-content">
                {data.abilities.map((n, index) => (
                  <p key={index}>{n.ability.name}</p>
                ))}
              </div>
            </div>
            <button onClick={handleMore}>More</button>
          </div>
          <div className="card card_more">
            <p>{data.height}</p>
            <p>{data.weight}</p>
          </div>
        </div>
      ) : (
        <div>
          <TailSpin type="Puff" color="purple" height={100} width={100} />
        </div>
      )}
    </div>
  );
}

export { Pokemon };



Solution 1:[1]

Youre right, this isn't the way you should do it in React. But your problem in your onClickButtonChange-Function is that youre only getting one element with document.querySelector(".card_more") and everytime you call it you get the same element back (No matter on which card you call it)

What you need to do is: Identify the single component elements. Thats most likely solved by passing a id/key value down via props and then putting this id on a parent-element (e.g. div.card) and you give it an id:

<div className="card card_main" id={props.keyvalue}>
.... 
</div>

And then in your onClickButtonChange-Function you call:

let cardMore = document.querySelector(`#${props.keyvalue} .card_more`);
...

This should give you the right element.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Raqha