When working on a project, I ran into a problem. In general, I get JSON data on the API and display the data in a table. In the table there are fields that can be changed (numeric).

It is necessary to make sure that after input to the input data, the information is sent to the Server by API. Everything is processed there, some data is counted, and then I need to retrieve all the data from the server again.

Of course, there is an onChange option for input, but I don’t want to send a request to the server every time you enter a single character and receive a lot of data again, this slows down the work (people entered 5 characters - 5 requests and 5 responses with fairly large data).

An example of my component:

class Table extends React.Component { handleOnChange(){ ... } render() { const data = this.props.data; return ( <table> ... <tbody> {data.map(item => ( <tr> <td>{item.id}</td> <td> <input type="text" placeholder={item.count} onChange={() => this.handleOnChange()} /> </td> </tr> )} </tbody> </table> ) } } 

How to make an idea? I tried to make a new component and process events there and send data by setTimeout, but I didn’t understand how to call a function from TableTr , for example, which is a Table and pass arguments to it (value input). Ref-s will not work like, there will be many TableTr components.

    1 answer 1

    Lodash to help. {Debounce, throttle} functions.

     import React, { Component } from 'react' import { debounce, throttle } from 'lodash' class Table extends Component { constructor(props) { super(props) this.state = { editingItem: {}, data: [], } } delayedСall = debounce((value, item) => { // отложеный вызов на 500ms //this.fetchApi() !!!! console.log(value) }, 500) delayedCutСall = throttle((value, item) => { // вызов раз в 500ms //this.fetchApi() !!!! console.log(value) }, 500) handleOnFocus = (item) => { this.setState({ editingItem: item }) } handleOnChange = (e, item) => { const { value } = e.target this.setState({ editingItem: { ...this.state.editingItem, value } }) this.delayedСall(value, item) this.delayedCutСall(value, item) } handleOnBlur = () => { this.setState({ data: this.state.data.map(i => (i.id === this.state.editingItem.id ? this.state.editingItem : i)), }) } render() { const { data, editingItem } = this.state; return ( <table> <tbody> {data.map(item => ( <tr key={item.id}> <td>{item.id}</td> <td> <input type="text" placeholder={item.count} value={item.id === editingItem.id ? editingItem.value : item.value} onChange={(e) => { this.handleOnChange(e, item) }} onFocus={(e) => { this.handleOnFocus(item) }} onBlur={this.handleOnBlur} /> </td> </tr> ))} </tbody> </table> ) } } 

    A useful example at a glance Note : If you need to be productive, the input should be put into a separate component, so that onChange would not render the entire table in time.

    If you use Redux, I recommend to pay attention to Redux-Saga where these functions are also implemented