When the game is over, I am trying to replace the underscores with the letters they missed one at a time using a setTimeout. This function swaps the underscore with the correct letter but, on the following render puts the letter back to the underscore and repeats this process until the end where it only displays the last missing letter. I need all the letters to fully swap out the state.underscores, which is an array of strings.
state.missingIndex is an array of numbers; missing letter indexes
word is the complete word the player is guessing
using useReducer hook to change state
React hooks and Typescript
const displayMissingLetters = () => {
let wrongWord: string[] = [];
state.losses.missingIndex.forEach((num, index) => {
setTimeout(() => {
wrongWord = state.underscores
.map((alpha: string, i: number) =>
alpha === "_" && word[i] === word[num] ? word[num] : alpha
);
dispatch({ type: "SET_UNDERSCORES", underscores: wrongWord });
}, index * 300);
});
}
This is what it looks like as of right now:
This is what wrongWord looks like in the console:
The problem is that when the timeout function fires, it has a stale copy of the state, set when all the timeouts are first scheduled.
It looks like you're using reducers here, so the easiest thing would be to handle this in a reducer. Reducers get the current state as they begin to run, so they shouldn't ever have old/stale state.
setTimeout(() => {
dispatch({ type: "REVEAL_LETTER", index: num });
}, index * 300)
Then move the logic that replaces an underscore with a letter, and saves that back in the state, to the reducer.