1

I've got a problem with my state which is late everytime. The app consists in checking your vocabulary in english or french but I've caught up with the issue that the state currentAnswer is always late by one character and the sentence 'Correct !' displays only if I write one more character. I can't fix the problem. All I can guess is that the state is not asynchronous but I can't make it asynchronous. Any Idea ?

import React from 'react';
import './App.css';

class App extends React.Component {

  constructor() {
    super();

    this.state = {
      words: [
        {
          francais: 'bonjour',
          anglais: 'hello',
        },
        {
          francais: 'manger',
          anglais: 'eat',
        },
        {
          francais: 'avoir',
          anglais: 'have',
        },
        {
          francais: 'faire',
          anglais: 'do',
        },
        {
          francais: 'jouer',
          anglais: 'play',
        }
    ],
    key: -1.4,
    currentWord: '',
    currentAnswer: '',
    correctAnswer: false,
    giveUp: false,
    currentScore: 0,
    scoreTotal: 0
    }
  }

  generateWord = () => {
    let index = Math.floor(Math.random() * (this.state.words.length + 1))
    if(index === this.state.key) {
      this.generateWord()
    }
    this.setState({currentWord: this.state.words[index]})
    this.setState({key: index})
  }

  validate = (e) => {
    e.preventDefault()
    const answer = e.target.value
    this.setState({ currentAnswer: answer})
    if (this.state.currentAnswer === this.state.currentWord.anglais) {
      this.setState({correctAnswer : true})
    }
  }

  showCorrection = (e) => {
    e.preventDefault()
    this.setState({giveUp: true})
    this.setState({scoreTotal: this.state.scoreTotal + 1})
  }

  nextWord = (e) => {
    e.preventDefault()
    this.setState({currentAnswer: ''})
    this.setState({ giveUp: false })
    this.setState({ correctAnswer: false })
    this.generateWord()
    if(this.state.correctAnswer) {
      this.setState({currentScore: this.state.currentScore + 1})
      this.setState({scoreTotal: this.state.scoreTotal + 1})
    }
  }

  componentDidMount() {
    this.generateWord()
  }

  render() {
    return (
      <div className="App">
        <p>Score: {this.state.currentScore}/{this.state.scoreTotal}</p>
        <h2 style={{
          color: "midnightblue",
          fontSize: "50px"
        }}>{this.state.currentWord?.francais}</h2> 
        <form action="">
          <input onChange={this.validate} value={this.state.currentAnswer} type="text" placeholder="Entrez la traduction anglaise"/>
          <button className="validation" onClick={this.showCorrection}>Give up</button>
          <button className="validation" onClick={this.nextWord}>Next</button>
        </form>      
        {this.state.correctAnswer ? <p>Correct !</p> : this.state.giveUp ? <p>La bonne réponse était: {this.state.currentWord?.anglais}</p>: ''}
      </div>
    )
  }
}

export default App;

1 Answer 1

1

Indeed setState() method is async and will not always update immediately.
But to fix your validation, simply compare the word to the current input instead of the current answer in state :

validate = (e) => {
    e.preventDefault()
    const answer = e.target.value
    this.setState({ currentAnswer: answer})
    if (answer === this.state.currentWord.anglais) {
      this.setState({correctAnswer : true})
    }
  }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.