Reputation: 43
I am trying to make a basic hangman game and here is my state :
static defaultProps = {
maxTries: 6,// maximum incorrect tries
imgs: [jpg0, jpg1, jpg2, jpg3, jpg4, jpg5, jpg6], //images changing through incorrect guesses
words: [
"donkey",
"apple",
"money",
"drink",
"sleep",
"legend",
"achievement"
]// list of words to be picked randomly
};
this.state = {
guessesNum: 0,//saves number of incorrect guesses
answer: "",//
guessed: [],//adds characters user typed if the answer contains
gameOver: false // checks if game is over
};
I have created a method gameSetup which will pick a random word from the array of words and set the answer also guessed in beginning is _ _ _ _ _ _ so when user makes a correct guess it is replaced
componentDidMount() {
this.gameSetup();
}
gameSetup = () => {
let word = this.props.words[
Math.floor(Math.random() * this.props.words.length)
];
console.log(word);
let guessedArray = [];
for (let i = 0; i < word.length; i++) {
guessedArray.push("_");
}
this.setState(st => {
return { answer: word, guessed: guessedArray };
});
};
The problem is when user is making guesses lets say the answer is apple
and the guessed array becomes ['a','p','p','l','e']; and I am checking if
guessed.join('')===answer then gameOver:true
but even if they are the same game over is being changed to true only on next try , because it is checking the if condition before actually setState has finished since it is asynchronous
This is how I am updating the state
userGuess = char => {
let indexes = [];
for (let i = 0; i < this.state.answer.length; i++) {
if (this.state.answer[i] === char) {
indexes.push(i);
}
}
if (indexes.length === 0) {
this.setState(st => {
return { guessesNum: st.guessesNum + 1 };
});
} else {
indexes.forEach(ind => {
this.setState(st => {
return { guessed: this.updateArray(st.guessed, ind, char) };
});
});
}
if (this.state.guessed.join("") === this.state.answer) {
this.setState({ gameOver: true });
}
};
This is a method to update array
updateArray = (array, index, value) => {
array[index] = value;
return array;
};
How can I make it ask the condition only after the state is updated ?
Here is the JSX
render() {
return (
<div>
<img src={this.props.imgs[this.state.guessesNum]} alt="0" />
<div
style={{
display: "flex",
width: "10%",
justifyContent: "space-evenly",
margin: "0 auto"
}}
>
{this.state.guessed.map((char, index) => {
return <p key={index}>{char}</p>;
})}
</div>
<div className="letters">
<Button guess={this.userGuess} />
</div>
</div>
);
}
And this is the Button component (acutally it holds all Buttons)
import React, { Component } from "react";
export default class Button extends Component {
handleGuess = e => {
this.props.guess(e.target.textContent);
};
render() {
return (
<div>
<button onClick={this.handleGuess}>a</button>
<button onClick={this.handleGuess}>b</button>
<button onClick={this.handleGuess}>c</button>
<button onClick={this.handleGuess}>d</button>
<button onClick={this.handleGuess}>e</button>
<button onClick={this.handleGuess}>f</button>
<button onClick={this.handleGuess}>g</button>
<button onClick={this.handleGuess}>h</button>
<button onClick={this.handleGuess}>i</button>
<button onClick={this.handleGuess}>j</button>
<button onClick={this.handleGuess}>k</button>
<button onClick={this.handleGuess}>l</button>
<button onClick={this.handleGuess}>m</button>
<button onClick={this.handleGuess}>n</button>
<button onClick={this.handleGuess}>o</button>
<button onClick={this.handleGuess}>p</button>
<button onClick={this.handleGuess}>q</button>
<button onClick={this.handleGuess}>r</button>
<button onClick={this.handleGuess}>s</button>
<button onClick={this.handleGuess}>t</button>
<button onClick={this.handleGuess}>u</button>
<button onClick={this.handleGuess}>v</button>
<button onClick={this.handleGuess}>w</button>
<button onClick={this.handleGuess}>x</button>
<button onClick={this.handleGuess}>y</button>
<button onClick={this.handleGuess}>z</button>
</div>
);
}
}
Upvotes: 1
Views: 56
Reputation: 10873
setState
acepts a second param, which is a callback function invoked after state is changed:
this.setState(st => {
return {
guessesNum: st.guessesNum + 1
};
}, () => {
if (this.state.guessed.join("") === this.state.answer) {
this.setState({
gameOver: true
});
}
});
Upvotes: 4