Reputation: 655
I bet this has something to do with asynchronicity.
Basically, I am checking if a string (an answer to a question) already exists, and if so, the page should just display a message, otherwise should add the new question to an array.
So in order to refactor the code, I have created a function called isDuplicateAnswer
(yes, it's bound to the component). Here is the code for it:
isDuplicateAnswer() {
if (this.state.answersToCurrentQuestion.length > 0) {
this.state.answersToCurrentQuestion.map(answer => {
if (this.state.answerTextTyped === answer.text) {
console.log("true"); // executed twice but then adds it to the array (not supposed to)
return true;
}
});
}
}
Based on this check the code will do the following:
if (
event.target.id === "submitAnswer" &&
this.state.answerTextTyped !== null &&
this.isDuplicateAnswer()
) {
console.log("Something is wrong"); // This line is never executed (no log, no message)
return this.props.handleMessage(
"There is already another answer with this text. Please add a different one."
);
} else if (
event.target.id === "submitAnswer" &&
this.state.answerTextTyped !== null &&
!this.isDuplicateAnswer()
) {
console.log("Everything OK"); // not displayed but rest of the code goes through (answer added)
this.setState({ answerText: this.state.answerTextTyped }, () => {
(() => {
let answersToCurrentQuestion = [
...this.state.answersToCurrentQuestion,
];
answersToCurrentQuestion.push({
text: this.state.answerText,
isCorrect: this.state.isCorrectAnswer,
});
this.setState({ answersToCurrentQuestion });
if (this.state.isCorrectAnswer === true) {
this.incrementCorrectAnswers();
}
})();
(() => {
this.props.handleMessage("");
this.setState({
isValid: true,
isCorrectAnswer: false,
answerTextTyped: null,
});
this.refreshAnswerTypedForm();
this.getAnswerTypedForm();
})();
});
}
My problem is that if isDuplicateAnswer
is false
, as my log says "Everything is Ok", but when it returns true
, the answer is created, resulting in an error due to the HTML key being not unique, even though the log from isDuplicateAnswer
is displayed twice.
Given that the other two checks in the guard are working correctly, what am I doing wrong here?
EDIT
this is the state right before clicking on "Add Answer", which id is submitAnswer
Upvotes: 1
Views: 6890
Reputation: 932
There are multiple things wrong in your code. I will list the ones that are most obvious to me:
1) Your isDuplicateAnswer()
method will always return undefined
which under if
condition will always evaluate to false
. That is why Something is wrong
is never executed - it will never go to that block.
2) This one is linked to 1)
above. Basically map
doesn't return a boolean
, moreover you have to return the result of the function which you're not doing as well. To fix this, use a method like some which does return a boolean:
isDuplicateAnswer() {
return this.state.answersToCurrentQuestion.some(answer => this.state.answerTextTyped === answer.text);
// If we find that answer already exists, some will return true, otherwise false.
}
3) In the 2nd block, do not check for event.target.id === "submitAnswer" && this.state.answerTextTyped !== null
twice. Just do:
if (event.target.id === "submitAnswer" && this.state.answerTextTyped !== null) {
if (isDuplicateAnswer()) {
console.log("Something is wrong");
return this.props.handleMessage("There is already another answer with this text. Please add a different one.");
// No setState call to change anything.
} else {
// Call setState and add your answer.
}
Upvotes: 3