0

I am utilizing React-Bootstrap for a simple text box component. Right now, the callback is called every time the user edits the textbox, hence it is called back when every letter is called

<Form.Group controlId="Id">
    <Form.Label>Id</Form.Label>
    <Form.Control style = {{marginLeft: 10}} name="Idstate" onChange={this.handleChange} defaultValue = {this.state.idstate}/>

</Form.Group>

The code above is my form group

handleChange = (event) => {
    event.persist()
    const name = event.target.name
    if (name == "Idstate"){
        this.setState({idstate: event.target.value})
        this.state.idstate = event.target.value;
        Apiservice.updatetabletopmenudata(this.tableid, event.target.value, "idstate")
    }
    console.log(this.state)
}

This results in a really laggy process, and sometimes the data isn't saved properly

Is there any way for the callback to be executed only after the user has finished editing the text box?

Dustyik
  • 69
  • 1
  • 6

2 Answers2

0

This is because every time a state changes the component re-renders.So, you can avoid unnecessary renders by creating a variable in the state state = {fromOnChange: false} which should always be false and whenever there is a change in the input text field, handle like below

handleChange(event) {
    this.setState({
      fromOnChange: true,
    });
  }

And when the state updates keep a life cycle method that checks wheather to render the component or not :

shouldComponentUpdate(nextProps, nextState) {
    if (!nextState.fromOnChange) {
      return true;
    } else {
      return false;
    }
  }

After that whenever user had finished editing the text fields and submits the data then change the fromOnchange: false so that component renders only on onsubmit.

handleSubmit(event) {
    //Your API/function call goes here
    // and on success change the state so that it renders
    this.setState({
          fromOnChange: false
        });
  }

sharan kenam
  • 195
  • 1
  • 11
0

First, fixing errors before performance:

Using defaultValue would create an uncontrolled component - only the default value will be set from React, then ignore any state changes.

If you need to control the value from React, please use value:

    <Form.Control ... value={this.state.idstate} />

Also, never modify state directly, this.setState({idstate: event.target.value}) is enough, no need for this.state.idstate = ... - but the operation is asynchronous (see the link above), so console.log(this.state) is meaningless inside the handleChange - you can console.log inside render or just use React DevTools to view the current state (both for classes and hooks).


Second, performance:

React state update is NOT slow by itself, it's pretty optimized. If you want to delay a slow Apiservice, you may try following:

handleChange = (event) => {
    const name = event.target.name
    const value = event.target.value
    if (name == "Idstate"){
        this.setState({idstate: event.target.value})
        setTimeout(() =>
            Apiservice.updatetabletopmenudata(this.tableid, value, "idstate")
        )
    }
}
Aprillion
  • 21,510
  • 5
  • 55
  • 89