I know there are many questions about removeEventListener on stackoverflow, but none of the answers have worked for me.
I am also not sure if removeEventListener is the issue causing problem.
i wrote 2048 game clone, but with every arrow click eventListener fires 2 times more than previously (2,4,8,16...) so after around 10 clicks app stops working.
I spent hours trying to find the issue but cannot find it...
The entire app code is below, its written in react:
import "./Board.css"
import {useEffect, useState} from "react";
import {v4} from "uuid"
const Board = () => {
const [globalBoard, setGlobalBoard] = useState(null)
useEffect(()=>{
initializeGame()
},[])
useEffect(()=>{
const handleGame = (e, board) => {
if (e.key !== "ArrowUp" &&
e.key !== "ArrowDown" &&
e.key !== "ArrowLeft" &&
e.key !== "ArrowRight"
) return
if (e.key === "ArrowUp") {
//take all numbers up
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 4; j++) {
let k = 0
while (board[i][j] === 0 && k < 3) {
if (i === 0) {
board[i][j] = board[i + 1][j]
board[i + 1][j] = board[i + 2][j]
board[i + 2][j] = board[i + 3][j]
board[i + 3][j] = 0
}
if (i === 1) {
board[i][j] = board[i + 1][j]
board[i + 1][j] = board[i + 2][j]
board[i + 2][j] = 0
}
if (i === 2) {
board[i][j] = board[i + 1][j]
board[i + 1][j] = 0
}
k++
}
}
}
//summarize all numbers
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 4; j++) {
if (board[i][j] !== 0 && board[i][j] === board[i + 1][j]) {
board[i][j] *= 2
if (i === 0) {
board[i + 1][j] = board[i + 2][j]
board[i + 2][j] = board[i + 3][j]
board[i + 3][j] = 0
}
if (i === 1) {
board[i + 1][j] = board[i + 2][j]
board[i + 2][j] = 0
}
if (i === 2) {
board[i + 1][j] = 0
}
}
}
}
}
if (e.key === "ArrowDown") {
//take all numbers down
for (let i = 3; i > 0; i--) {
for (let j = 0; j < 4; j++) {
let k = 0
while (board[i][j] === 0 && k < 3) {
if (i === 3) {
board[i][j] = board[i - 1][j]
board[i - 1][j] = board[i - 2][j]
board[i - 2][j] = board[i - 3][j]
board[i - 3][j] = 0
}
if (i === 2) {
board[i][j] = board[i - 1][j]
board[i - 1][j] = board[i - 2][j]
board[i - 2][j] = 0
}
if (i === 1) {
board[i][j] = board[i - 1][j]
board[i - 1][j] = 0
}
k++
}
}
}
//summarize all numbers
for (let i = 3; i > 0; i--) {
for (let j = 0; j < 4; j++) {
if (board[i][j] !== 0 && board[i][j] === board[i - 1][j]) {
board[i][j] *= 2
if (i === 3) {
board[i - 1][j] = board[i - 2][j]
board[i - 2][j] = board[i - 3][j]
board[i - 3][j] = 0
}
if (i === 2) {
board[i - 1][j] = board[i - 2][j]
board[i - 2][j] = 0
}
if (i === 1) {
board[i - 1][j] = 0
}
}
}
}
}
if (e.key === "ArrowLeft") {
//take all numbers to the left
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 3; j++) {
let k = 0
while (board[i][j] === 0 && k < 3) {
if (j === 0) {
board[i][j] = board[i][j + 1]
board[i][j + 1] = board[i][j + 2]
board[i][j + 2] = board[i][j + 3]
board[i][j + 3] = 0
}
if (j === 1) {
board[i][j] = board[i][j + 1]
board[i][j + 1] = board[i][j + 2]
board[i][j + 2] = 0
}
if (j === 2) {
board[i][j] = board[i][j + 1]
board[i][j + 1] = 0
}
k++
}
}
}
//summarize all numbers
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 3; j++) {
if (board[i][j] !== 0 && board[i][j] === board[i][j + 1]) {
board[i][j] *= 2
if (j === 0) {
board[i][j + 1] = board[i][j + 2]
board[i][j + 2] = board[i][j + 3]
board[i][j + 3] = 0
}
if (j === 1) {
board[i][j + 1] = board[i][j + 2]
board[i][j + 2] = 0
}
if (j === 2) {
board[i][j + 1] = 0
}
}
}
}
}
if (e.key === "ArrowRight") {
//take all numbers to the left
for (let i = 0; i < 4; i++) {
for (let j = 3; j > 0; j--) {
let k = 0
while (board[i][j] === 0 && k < 3) {
if (j === 3) {
board[i][j] = board[i][j - 1]
board[i][j - 1] = board[i][j - 2]
board[i][j - 2] = board[i][j - 3]
board[i][j - 3] = 0
}
if (j === 2) {
board[i][j] = board[i][j - 1]
board[i][j - 1] = board[i][j - 2]
board[i][j - 2] = 0
}
if (j === 1) {
board[i][j] = board[i][j - 1]
board[i][j - 1] = 0
}
k++
}
}
}
//summarize all numbers
for (let i = 0; i < 4; i++) {
for (let j = 3; j > 0; j--) {
if (board[i][j] !== 0 && board[i][j] === board[i][j - 1]) {
board[i][j] *= 2
if (j === 3) {
board[i][j - 1] = board[i][j - 2]
board[i][j - 2] = board[i][j - 3]
board[i][j - 3] = 0
}
if (j === 2) {
board[i][j] = board[i][j - 1]
board[i][j - 1] = board[i][j - 2]
board[i][j - 2] = 0
}
if (j === 1) {
board[i][j] = board[i][j - 1]
board[i][j - 1] = 0
}
}
}
}
}
//check if previous board differs from the current one (if it does not, we don't want to add extra number)
console.log(globalBoard)
let arrayChanged = false
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
if (globalBoard[i][j] !== board[i][j]){
arrayChanged = true
}
}
}
if (arrayChanged){
//draw a spot on the board
let number1 = Math.floor(Math.random() * 4)
let number2 = Math.floor(Math.random() * 4)
//check if the spot is empty - does not contain a number
while (board[number1][number2] !==0){
number1 = Math.floor(Math.random() * 4)
number2 = Math.floor(Math.random() * 4)
}
//create a new number: 2 or 4 (with 80% chance that it will be 2) and place it in the selected spot
board[number1][number2] = (Math.floor(Math.random() * 10) >= 8) ? 4 : 2;
setGlobalBoard([...board])
}
}
if (globalBoard){
let board = [[...globalBoard[0]],[...globalBoard[1]],[...globalBoard[2]],[...globalBoard[3]]]
window.addEventListener("keydown",(e)=> handleGame(e,board))
}
return ()=> window.removeEventListener("keydown",handleGame)
},[globalBoard])
const initializeGame = () => {
let board = []
for (let i = 0; i < 4; i++) {
board.push([])
for (let j = 0; j < 4; j++){
board[i].push(0)
}
}
let randomNr1 = Math.floor(Math.random()*4)
let randomNr2 = Math.floor(Math.random()*4)
//push first number
board[randomNr1][randomNr2] = 2;
let newRandomNr1;
let newRandomNr2;
do {
newRandomNr1 = Math.floor(Math.random()*4)
newRandomNr2 = Math.floor(Math.random()*4)
}while (randomNr1===newRandomNr1 && randomNr2===newRandomNr2)
board[newRandomNr1][newRandomNr2] = (Math.floor(Math.random()*10) >= 8) ? 4 : 2
setGlobalBoard(board)
return board
}
return (
<div className="board">
{globalBoard && globalBoard.map((array)=>{
return array.map((el)=>{
return <div key={v4()} className="element">{el === 0 ? "" : el}</div>
})
})}
</div>
);
};
export default Board;
Change to this
To delete a listener, you need to pass the same function to it as to create a listner.
We create an intermediate function beginHandleGame
and pass it to create a listner and delete it.
let board;
const beginHandleGame (e) => {
handleGame(e,board);
}
if (globalBoard){
board = [[...globalBoard[0]],[...globalBoard[1]],[...globalBoard[2]],[...globalBoard[3]]]
window.addEventListener("keydown", beginHandleGame);
}
return ()=> window.removeEventListener("keydown", beginHandleGame)