the values of value 1 and 2 and 3 which stored in the props are Math.floor(Math.random() * 100) so what I want to know when I setState and the value of numQuestions , numCorrect change and the render method is being called as I know why this render didn't make the three values 1,2,3 reproduced again and their values change with each click of the two buttons .
class App extends Component {
constructor(props) {
super(props)
this.proposedAnswer = Math.floor(Math.random() * 3) this.props.value1 this.props.value2 this.props.value3;
this.state = {
numQuestions : 0,
numCorrect : 0,
}
}
rightanswer= ()=> {
if(this.proposedAnswer === this.props.value1 this.props.value2 this.props.value3){
this.setState((oldstate)=> ({
numCorrect : oldstate.numCorrect =1 ,
numQuestions : oldstate.numQuestions = 1 ,
}))
}else{
this.setState((oldstate)=> ({
numQuestions : oldstate.numQuestions = 1 ,
}))
}
}
falseanswer= ()=> {
if(this.proposedAnswer !== this.props.value1 this.props.value2 this.props.value3){
this.setState((oldstate)=> ({
numCorrect : oldstate.numCorrect =1 ,
numQuestions : oldstate.numQuestions = 1 ,
}))
}else{
this.setState((oldstate)=> ({
numQuestions : oldstate.numQuestions = 1 ,
}))
}
}
render() {
return (
<div className="App">
<div className="game">
<h2>Mental Math</h2>
<div className="equation">
<p className="text">{`${this.props.value1} ${this.props.value2}
${this.props.value3} = ${this.proposedAnswer}`}</p>
</div>
<button onClick={() => this.rightanswer()}>True</button>
<button onClick={() => this.falseanswer()}>False</button>
<p className="text">
Your Score: {this.state.numCorrect}/{this.state.numQuestions}
</p>
</div>
</div>
);
}
}
export default App;
CodePudding user response:
Arrow functions don't have a this
binding (more info here). You're also calling them on the onClick
of the button
with this.falseanswer
. So the class can't find the binding and hence the function returns nothing cause it's like it doesn't exist. Additionally when we pass functions to event handlers and the functions have no arguments the best practice is to just pass the function like this: onClick={myFunciton}
.
So in your case I'd turn these arrow functions into methods, bind them at the constructor
and call them on the onClick
event
constructor(props) {
super(props)
this.proposedAnswer = Math.floor(Math.random() * 3) this.props.value1 this.props.value2 this.props.value3;
this.state = {
numQuestions : 0,
numCorrect : 0,
}
this.falseAnswer = this.falseAnswer.bind(this);
}
falseAnswer () { ...}
render () {
return (
<button onClick={this.falseAnswer}>False</button>
);
}
CodePudding user response:
Your component is re-rendering when the state changes. However, your props do not change because you are not passing in new props from the parent component, so value1
, value2
, and value3
remain the same.
If you want your value
s to change on a state change, one approach is to move all of your value
s to state, initialize them when the component mounts, and update them when your component updates:
constructor(props) {
super(props);
this.state = {
numQuestions: 0,
numCorrect: 0
};
}
componentDidMount() {
this.generateValues();
}
componentDidUpdate(prevProps, prevState) {
if (this.state.numQuestions !== prevState.numQuestions) {
this.generateValues();
}
}
generateValues = () => {
const values = [...Array(3)].map(() => Math.floor(Math.random() * 100));
const correctAnswer = values.reduce((a, b) => a b, 0);
const proposedAnswer = Math.floor(Math.random() * 3) correctAnswer;
this.setState({
value1: values[0],
value2: values[1],
value3: values[2],
correctAnswer: correctAnswer,
proposedAnswer: proposedAnswer
});
};