Search code examples
javascriptreactjsevent-handlingonchangehtml-input

onChange event Function is Lagging In My React App


In my react app on user register page am trying to check weather a username already exist or not my code is

checkUserName = (e) => {
this.setState({username:e.target.value});
let username = this.state.username;
db.collection("users").doc(username).get()
.then((snapshot)=>{
 if(snapshot.exists)
 {
   this.setState({usernameExistError:"show"}); *//this is classname of error div*
   this.setState({isUsernameOk:false})
   console.log(this.state.usernameExistError,this.state.isUsernameOk);
 }
 else
 {
   this.setState({usernameExistError:"hide"});
   this.setState({isUsernameOk:true})
   console.log(this.state.usernameExistError,this.state.isUsernameOk);
 }
 })
 }

all works fine when i check console.But The Problem is when i pressed a key in my input , state username is blank and when i type the second letter then the username state reads the first letter. so when an existing username is found only when the data is like "EXISTINGUSERNAME" + SOME_KEY_PRESS How can i solve this...Thanks In Advance


Solution

  • Because you use the state at the moment when it is still old, since the setState() occurs asynchronously.

    To solve your problem, you should set the value to a variable and use it in the future:

    const { target: { value: username } } = e;
    
    this.setState({ username });
    db.collection("users").doc(username).get()
    
    // ...the rest of code 
    

    Or perform all actions depending on the current state in the callback:

    this.setState({ username: e.target.value }, () => {
      db.collection("users").doc(this.state.username).get()
    
      // ...the rest of code 
    });
    

    Example of setState() async behavior:

    class TestComponent extends React.Component {
      state = {
        data: 1
      }
      
      onClick = () => {
        console.log(`data before set: ${this.state.data}`);
        
        const newData = this.state.data + 1;
        
        this.setState(
          { data: newData }, 
          () => console.log(`data in callback: ${newData}`)
        );
        
        console.log(`data after set: ${this.state.data}`);
        console.log(`actual current data: ${newData}`);
      }
      
      render() {
        return <div onClick={this.onClick}>Click Me!</div>;
      }
    };
    
    ReactDOM.render(<TestComponent />, document.getElementById('app'));
    #app {
      cursor: pointer;
    }
    <script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
    
    <div id="app"></div>