-1

First of all I want to know if I am right about cause of the problem.

const updateScore = (isCorrect) => {
  // Update Game Variables
  if (isCorrect === true) {
    counter++;
    score += 100;
  }
};

// Reset Styling
const resetLoadedQuestionStyling = (isCorrect) => {
  questionScreen.style.display = 'none';
  answerArr.forEach(answer => {
    answer.classList.remove('correct');
    answer.classList.remove('wrong');
    answer.classList.remove('disable');
  });
  updateScore(isCorrect);
};

const styleAnswer = (div, isCorrect) => {
  if (isCorrect === true) {
    div.classList.add('correct');
  } else {
    div.classList.add('wrong');
    for (let i = 0; i < answerArr.length; i++) {
      if (i === currentQuestion.correct) {
        answerArr[i].classList.add('correct');
      }
    }
  }

  // Prevent Second Check
  answerArr.forEach(answer => {
    answer.classList.add('disable');
  });

  // Reset Styling
  setTimeout(() => {
    resetLoadedQuestionStyling(isCorrect);
  }, 3000);
};

const checkAnswer = (div, index) => {
  const userChoice = index;
  // Default Answer State
  let isCorrect = false;
  if (userChoice === currentQuestion.correct) {
    isCorrect = true;
  }
  styleAnswer(div, isCorrect);
};

answerArr.forEach((div, index) => {
  div.addEventListener('click', () => {
    checkAnswer(div, index);
  });
});

  1. My counter updates 1,time, that 2 times... and I think the cause of this issue is that my EventListener is in a forEach loop, is that right?

  2. How to prevent it?

Thanks!

EDIT: Addded more of the code in order to get my idea better.

EDIT: answerArr is array of 4 divs in my HTML

terrymorse
  • 5,564
  • 1
  • 14
  • 19
kasmirski
  • 9
  • 3
  • 2
    Please, [edit] your question and provide a [mre]. – Sebastian Simon Jan 27 '21 at 22:07
  • 1
    Use [event delegation](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_delegation) instead of assigning multiple events — it’s more maintainable, and applies to dynamically added elements. E.g., use an [event argument](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#The_event_listener_callback)’s [`target`](https://developer.mozilla.org/en-US/docs/Web/API/Event/target). See [the tag info](https://stackoverflow.com/tags/event-delegation/info) and [What is DOM Event delegation?](https://stackoverflow.com/q/1687296/4642212). – Sebastian Simon Jan 27 '21 at 22:07
  • @SebastianSimon please read the problem once more. – kasmirski Jan 27 '21 at 22:12
  • My elements (divs) are not on each other in order to experience bubbling effect. – kasmirski Jan 27 '21 at 22:13
  • You added so much more code, but it’s still unclear what `answerArr` is. See [How to create Stack Snippets](https://meta.stackoverflow.com/q/358992/4642212) and make sure the problem is reproducible when hitting the “Run” button. – Sebastian Simon Jan 27 '21 at 22:14
  • @SebastianSimon answerArr is an array of four divs. They are displayed flex and do not go on top of each other. – kasmirski Jan 27 '21 at 22:15
  • There can be n number of reasons ... when is answerArr for each loop called? on document load? – Oo-_-oO Jan 27 '21 at 22:25
  • 1
    Your `updateScore(isCorrect)` is inside a forEach loop, so it is called `answerArr.length` times for each call to `resetLoadedQuestionStyling`. Did you consider moving `updateScore` outside of the forEach loop? – terrymorse Jan 27 '21 at 22:30
  • @terrymorse yup I just saw that, but the problem now is that score updates 1 than 2, that 3 three times – kasmirski Jan 27 '21 at 22:36
  • @terrymorse I updated once more. Thx tho. – kasmirski Jan 27 '21 at 22:40
  • Make sure you’re not binding the event listeners multiple times. All this can be debugged using the [browser console (dev tools)](https://webmasters.stackexchange.com/q/8525) (hit `F12`). Inspect the elements, see how many event listeners are bound. You’d do everyone here a favor by simply editing your question and creating a stack snippet with the minimal code necessary to reproduce the problem. I’ve already linked to the relevant help center sections. Unless this is done, you’ll just receive one guess after the next. – Sebastian Simon Jan 27 '21 at 22:43
  • @SebastianSimon but the problem should be exactly that my function is in a forEach array, but there is no way to pass directly the parameters to the eventlistener – kasmirski Jan 27 '21 at 22:51

1 Answers1

0

There may be a setTimeout-related issue. Every time an answer is clicked, the counter is set to be incremented after 3 seconds.

Here's the sequence when an answer is clicked:

'click'

  checkAnswer ->
    styleAnswer ->
      setTimeout =>
        resetLoadedQuestionStyling ->
          updateScore ->
            counter++

Below is the code with all of the unrelated lines removed. It does increment the counter after every click, but only after 3 seconds.

const answerArr = [...document.querySelectorAll('button')];
let counter = 0;
const span = document.getElementById('counter');

const updateScore = (isCorrect) => {
  if (isCorrect === true) {
    counter++
  }
  span.innerText = counter;
}

const resetLoadedQuestionStyling = (isCorrect) => {
  updateScore(isCorrect)
}

const styleAnswer = (div, isCorrect) => {

  // Reset Styling after 3 seconds
  setTimeout(() => {
    resetLoadedQuestionStyling(isCorrect);
  }, 3000);
}

const checkAnswer = (div, index) => {
  styleAnswer(div, true);
}

answerArr.forEach((div, index) => {
  div.addEventListener('click', () => {
    checkAnswer(div, index);
  });
});
<button>Answer 1</button><br>
<button>Answer 2</button><br>
<button>Answer 3</button><br>
<button>Answer 4</button><br>

<p>Counter: <span id="counter"></span></p>
terrymorse
  • 5,564
  • 1
  • 14
  • 19
  • I removed the setTimeout completely now and tested. Unfortunately it is not the cause of the problem. After fixing the problem that You suggested previously, now I am not updating score each time 4 times, but the sequence is like 1,1,2,2 – kasmirski Jan 27 '21 at 23:03
  • @kasmirski The problem must be in some code that you have not posted. The code you posted works correctly, as I have show above. – terrymorse Jan 27 '21 at 23:10
  • Thank you so much for the help so far. It indeed is somewhere else. I have another event listener that runs the whole function like so: ``anotherArrayOfNineElelements.forEach(element => { element.addEventListener('click', () => { loadQuestion(element); }); });`` Where my ``loadQuestion`` is the function that I wrote above and the one that you recreated. Can it be the cause of the problem? – kasmirski Jan 27 '21 at 23:18