简体   繁体   中英

Onclick function for multiple buttons with same ID?

I have this component that loads some data with buttons. I have a function that gets button via ID and updates state/variable to that buttons value, then loads data based on that. However since all the button IDs are the same, it only works for the first button...

I'm not sure how to set unique IDs for each button since they're generated through a map() function, and even if i did know, i'm not sure how my function would then target each button without writing a function for each one...

Edit: I've set unique IDs for buttons now, still need to solve the other problem.

  return member.map((player, index) => (
    <>
      {" "}
      <React.Fragment key={index}>
        <br />{" "}
        <div>
          <br />
          {player.map((stats) => (
            <React.Fragment key={stats.player}>
              <div class="flex-child">
                <button id={'btn' + index} value={stats.player}>
                  {stats.player}
                </button>
                <p>{stats.role}</p>
                <p>{stats.win_rate}</p>
                <p>{stats.matches}</p>
                <p>{stats.total_battles} Total Battles</p>
                <p>{stats.score} / Points Earned</p>
              </div>
            </React.Fragment>
          ))}
        </div>
        <br />
      </React.Fragment>
    </>
  ));
};

export default SquadMembers;

here is index.js

import Head from "next/head";
import React, { useState } from "react";
import Teams from "../components/Teams";
import styles from "../../styles/Home.module.css";
import SquadMembers from "../components/SquadMembers";
import SquadData from "../components/SquadData";

export default function Home() {
  const [teams, setTeams] = useState([]);
  const [squads, setSquads] = useState([]);
  const [player, setPlayer] = useState("Player Name");
  const [squad, setSquad] = useState("default");
  const [loading, setLoading] = useState(false);

  function clicky() {
    if (!document.getElementById("btn")) {
    } else {
      setPlayer(document.getElementById("btn").value);
      loadPeople();
    }
  }

  if (typeof window === "object") {
    if (!document.getElementById("btn")) {
    } else {
      document.getElementById("btn").onclick = function () {
        clicky();
      };
    }
  }

  function handleChange(e) {
    setSquad(e.target.value);
  }

  const loadPeople = async () => {
    setLoading(true);
    const req = await fetch(`/api/player/${player}`);
    const json = await req.json();
    setTeams(json);
    setLoading(false);
  };

  const loadSquad = async () => {
    setLoading(true);
    const req = await fetch(`/api/squad/${squad}`);
    const json = await req.json();
    setSquads(json);
    setLoading(false);
    setTeams([]);
  };

  return (
    <div className={styles.main}>
      <main className={styles.main}>
        <h1>Silph Team Finder</h1>
        <br />
        <div>
          <select value={squad} onChange={handleChange}>
            <option value="default" selected disabled hidden>
              Choose here
            </option>
            <option value="a342">Lots of options, cut them to save space</option>
          </select>
          <button onClick={() => loadSquad()}>Load</button>

          <input
            value={player}
            id="player"
            onChange={(e) => setPlayer(e.target.value)}
          />
          <button onClick={() => loadPeople()} id="pbtn">
            Load
          </button>
          {loading && <div className={styles.load}>LOADING</div>}
        </div>
        <div className={styles.teams}>
          <SquadData squadz={squads} />
          <Teams teams={teams} />
          <div class="player-container">
            <SquadMembers squadz={squads} />
          </div>
        </div>
      </main>
    </div>
  );
}

Would be much easier to have something like:

<button value={stats.player} onClick={() => handleClick(stats.player)}>
   {stats.player}
</button>

...

const handleClick = (player) => {
   setPlayer(player);
   loadPeople();
}

In this way you don't need id for button . Not only but you will avoid warning on same id for multiple elements.

Then I would like to talk about loadPeople() . If I understood correctly in this function you are using player that would be setted by setPlayer . This is not a good approach. setPlayer is async and you could take an old value of player . Much better pass the last player value directly to loadPeople function. Something like:

const handleClick = (player) => {
   setPlayer(player);
   loadPeople(player);
}

const loadPeople = async (newPlayer) => {
   setLoading(true);
   const req = await fetch(`/api/player/${newPlayer}`);
   const json = await req.json();
   setTeams(json);
   setLoading(false);
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM