Search code examples
javascriptreactjsalertevent-listener

React adding multiple event-listeners to same click event


I have a function in React, playerJoin(), that executes whenever a certain button is clicked. The function sends info to the server and the server checks if the info matches what it has stored. If it does not match, an alert() function is fired.

The problem I'm having is when I click the button the first time and the info does not match, one alert pops up. However, if I try again and it's still wrong, two alerts pop up and so on. I used console.log to see how many times the function runs and it runs only once no matter how many times the alert pops up.

This is the react code that I have. I didn't include the back-end code and the other react functions because I don't think they're very relevant.

function Home() {
  const [input, setInput] = useState({
    displayName: "",
    pin: "",
  });
  const { displayName, pin } = input;

  const navigate = useNavigate();

  function playerJoin() {
    socket.emit("player-join", displayName, pin);
    socket.on("game-found-status", (gameFound) => {
      if (gameFound) {
        navigate("/player/lobby");
      } else {
        alert("No game found with this pin.")
      }
    })
  }

  return (
    <div id="home" className="component-container-middle">
      <h1>Join a Game</h1>
      <div className="game-input-info">
        <p>Display Name</p>
        <input
          name="displayName"
          value={displayName}
          onChange={handleChange}
          ref={nameInputRef}
        />
        <p>Game Pin</p>
        <input name="pin" value={pin} onChange={handleChange} />
        <button onClick={playerJoin}>Join</button>
        <Link id="host-link" to="/host">
          Click here to host a game
        </Link>
      </div>
    </div>
  );
}

Solution

  • You need to add socket.on inside a useEffect hook, also make sure to socket.off after the component gets unmounted.

    useEffect(() => {
        socket.on("game-found-status", (gameFound) => {
          // your code
        });
    
        return () => {
          socket.off("game-found-status");
        };
      }, []);