Reputation: 449
I'm trying to build a simple game in React and I need to make an animation where a set of blocks change their color to orange for 1 sec and go back to white. This operation needs to happen one by one.
Here is my game with an array of divs:
And let's say the array is [1,3,5,6] I want to loop through that array and add a class with bg color to each div for a second and then removed it
I tried many things but the close I can get I that all the divs change their color at the same, not one by one
this is my code with a function that is starting by pressing "next lvl" and another async function
const displayBlocks = async (key) => {
let promise = new Promise((res,rej) => {
setTimeout(() => {
divArray.classList.remove('active');
res('color removed');
}, 500)
});
console.log(key);
ref.current.childNodes[key].classList.add('active');
let result = await promise;
return result;
}
const handleNewGame = () => {
blockArray = []
// generate array with random cells according to points
for (let i = 0;i< props.points;i++) {
let key = Math.floor(Math.random() * (props.board.length)) + 0;
displayBlocks(key).then((res) => {
console.log(res);
blockArray.push(key);
})
}
console.log(blockArray);
}
I tried many solutions with async or without but none of them worked. Can you tell me how can I stop the execution of the loop until the displayBlock functions are completed?
Upvotes: 1
Views: 1181
Reputation: 3411
If you share the full working code in some online code editor I can fix it, but for now, I will share some pseudo code that you can convert into real code.
The idea is, if you want your divs change color 1 by 1, then add the class also one by one, keep track of the time in your calculation. See the pseudo code below,
function displayBlock (index) {
let duration = 1000
let waitTime = index * duration
let thisDiv = divArray[index]
// Now wait for waitTime amount of time before adding the OrangeClass
setTimeout(() => {
thisDiv.addClass('OrangeClass')
//Now from this point, wait for another 1 sec and remove the OrangeClass
setTimeout(() => {
thisDiv.removeCLass('OrangeClass')
}, duration)
}, waitTime)
}
If you can perfectly implement it, it should work as per your expectation. Just do some trial and error.
You can do it. Cheers :)
Upvotes: 0
Reputation: 537
Note: Can't test it at the moment, might run into the same problem
Your displayBlocks
method is not awaitable. Have you tried something like
const displayBlocks = async (key) => {
return new Promise((res,rej) => { // return with promise to make it awaitable
setTimeout(() => {
divArray.classList.remove('active');
res('color removed');
}, 500)
});
console.log(key);
ref.current.childNodes[key].classList.add('active');
let result = await promise;
return result;
}
const handleNewGame = () => {
blockArray = []
// generate array with random cells according to points
for (let i = 0;i< props.points;i++) {
let key = Math.floor(Math.random() * (props.board.length)) + 0;
var res = await displayBlocks(key); // await should halt the loop
console.log(res);
blockArray.push(key);
}
console.log(blockArray);
}
Upvotes: 1