Open tangway opened 5 months ago
i separated the 2 conditions into 2 useEffects to help debug the situation, also added a .then()
promise to check that the first part of the animation runs
useEffect(() => {
if (numberOfAttempts === 4) {
// setGameHasEnded(true);
// first part of animation
controls.start({
scale: 1,
// x: [0, 0],
// y: [0, 0],
transition: { duration: 2.5, ease: 'easeInOut', delay: 5 },
}).then(() => {
console.log("First part of animation complete.")});
// second part of animation
// the timeout value has to be longer than the duration+delay in the first
// part of animation otherwise the second part will override the first part
setTimeout(() => {
controls.start({
// scale: [1, 0.9, 1.1, 1], // shake scale values
scale: [1, 0.8, 1],
transition: {
duration: 2.5,
repeat: 'Infinity',
repeatType: 'reverse',
ease: 'easeInOut',
},
});
}, 7600);
}
}, [numberOfAttempts]);
useEffect(() => {
if (correct === true) {
// setGameHasEnded(true);
// first part of animation
controls.start({
scale: 1,
// x: [0, 0],
// y: [0, 0],
transition: { duration: 2.5, ease: 'easeInOut', delay: 5 },
}).then(() => {
console.log("First part of animation runs.")});
// second part of animation
// the timeout value has to be longer than the duration+delay in the first
// part of animation otherwise the second part will override the first part
setTimeout(() => {
controls.start({
// scale: [1, 0.9, 1.1, 1], // shake scale values
scale: [1, 0.8, 1],
transition: {
duration: 2.5,
repeat: 'Infinity',
repeatType: 'reverse',
ease: 'easeInOut',
},
});
}, 7600);
}
}, [correct]);
added some other console log statements to track state of numberOfAttempts
and correct
the problem still persists, and console statements shows that in both cases the first part of the animation actually runs so we can be sure of that now
looking at the debug statements the only difference between when user reaches numberOfAttempts === 4
and when user gets correct answer correct === true
is that the correct
state changes to true.
one of the possible reasons the 1st part animation doesnt render is that it is overwritten by a re-render of the component as one of its state changes when it is being executed but i have yet to find out which state that is
using React Devtools could help to track the different state changes in each user flow
in 4 attempts player failed flow, this is the sequence of state changes as shown in React Devtools Profiler:
in 4 attempts, where player gets correct answer in the 4th attempt, this is the sequence of state changes that allowed the 2 step animation sequence to run correctly:
it could be that in the first flow that extra step in state change somehow interrupted the rendering of 1st part of the animation. the second flow updates all but 1 state in the first step and consists of only 2 steps
have reduced the first flow to only 2 steps in state change by combining 3 state changes into 1 useEffect but the problem stays the same
useEffect(() => {
console.log('useEffect numberOfAttempts:', numberOfAttempts);
if (numberOfAttempts === 4 && correct === false) {
setGameHasEnded(true);
setStartFlagAnimation(true);
setPlayerFailed(true);
}
}, [numberOfAttempts, correct]);
so with the above change, for 4 attempts player failed flow this is the sequence of state changes as shown in React Devtools Profiler:
continued working on the possibility that it's the extra number of steps in state change that caused the 1st part of the animation to be cancelled out. what if i could bundle all the state change into checkAnswer
function like what a correct answer flow does?
so i took out the above useEffect and placed what it does into a callback function in setNumberOfAttempts
:
const checkAnswer = event => {
const target = event.currentTarget;
if (!gameHasEnded) {
target.disabled = true;
setButtonClicked(buttonClicked.concat(target.id));
// setNumberOfAttempts(prevNumber => prevNumber + 1);
setNumberOfAttempts(prevNumber => {
const newNumber = prevNumber + 1;
if (newNumber === 4 && correct === false) {
setGameHasEnded(true);
setStartFlagAnimation(true);
setPlayerFailed(true);
}
return newNumber;
});
console.log('numberOfAttempts in !gameHasEnded: ', numberOfAttempts);
}
if (target.textContent === correctAnswer) {
// when answer is correct
setCorrect(true);
setGameHasEnded(true);
setCorrectButton(target.id);
setScore(score + 1);
setStartFlagAnimation(true);
} else {
// when answer is wrong
setCorrect(false);
}
};
so now with 4 attempts failed this is the state change:
all in 1 step and this might totally explain why it worked!!!
the animation sequence renders properly when
correct === true
but for some reason the first part of the sequence is skipped whennumberOfAttempts === 4
even though they're in the same if statementin the case where
numberOfAttempts === 4
and at the 4th attempt the user gets the answer correct the 2 step animation sequence is rendered properly