I'm building an tic-tac-toe app in React JS, but useEffect in react behaving pretty weired for me. this is full project url: https://github.com/vyshnav4u/react-tic-tac-toe
Snippet Having problem
You can see that i'm calling isWinner function inside useEffect, in winning condition is meet, isWinner should be print "finish" on console and return true. Now it's printing "finish" on console correctly but not return or printing true inside useEffect.
useEffect(() => {
if (currentSquare >= 0) {
let winFlag = isWinner(currentSquare);
// this should print true when winning condition is meet,
// but it's always printing false
console.log(winFlag);
if (winFlag) {
alert("won");
}
}
}, [currentSquare, value]);
//isWinner function
const isWinner = (currentIndex) => {
pattern.forEach((singlePattern, index) => {
if (singlePattern.includes(currentIndex)) {
let tempIndex_0 = singlePattern[0];
let tempIndex_1 = singlePattern[1];
let tempIndex_2 = singlePattern[2];
if (
value[tempIndex_0] == value[tempIndex_1] &&
value[tempIndex_1] == value[tempIndex_2]
) {
console.log("finish");
return true;
}
}
});
return false;
};
Edit: The issue was sorted, it was not a problem caused by useEffect but with the incorrect use of forEach in isWinner function please see the verified answer.
Array.prototype.forEach
is a void return. The return true
isn't a return for the isWinner
callback, it's only a return for the .forEach
callback.
If I'm understanding the purpose of the isWinner
function you want to return true|false if the wining condition is met or not.
You could keep an isWon
variable initialized false and only set true upon the condition.
const isWinner = (currentIndex) => {
let isWon = false;
pattern.forEach((singlePattern, index) => {
if (singlePattern.includes(currentIndex)) {
const tempIndex_0 = singlePattern[0];
const tempIndex_1 = singlePattern[1];
const tempIndex_2 = singlePattern[2];
if (
value[tempIndex_0] == value[tempIndex_1] &&
value[tempIndex_1] == value[tempIndex_2]
) {
console.log("finish");
isWon = true;
}
}
});
return isWon;
};
Or refactor the code to be a little more functional.
const isWinner = (currentIndex) => {
return pattern.some((singlePattern, index) => {
if (singlePattern.includes(currentIndex)) {
const [tempIndex_0, tempIndex_1, tempIndex_2] = singlePattern;
if (
value[tempIndex_0] == value[tempIndex_1] &&
value[tempIndex_1] == value[tempIndex_2]
) {
console.log("finish");
return true;
}
}
return false;
});
};