0

I'm creating my implementation of fixed-data-table-2 (npm) where an edit button changes cells to input's, which may be edited and then saved (post).

enter image description here

But there's a major problem... It's too slow the typing, because I'm updating the entire array (in state) every single time that onChange is triggered on the cell.

Event Handler (Table)

import reactUpdate from "react/lib/update";
onChangeEditableCell(field, rowIndex, newValue) {
    const data = reactUpdate(this.state.data, {[rowIndex]: {[field]: {$set: newValue}}})
    this.setState({data : data});
}

Event Handler (Cell)

onChange(e) {
    e.preventDefault();
    const newValue = e.target.value;
    this.props.onHandleInput(this.props.field, this.props.rowIndex, newValue);
}

render() {
    const {rowIndex, field, data, editMode, onHandleInput, ...props} = this.props;

    return (
        <Cell {...props}>
            {editMode ? <input onChange={this.onChange} className="text-cell-edit" type="text" value={this.getCell()} /> : data[rowIndex][field]}
        </Cell>
    );
}

This is obviously a bad idea... How may I achieve the same but performance-wise?

Note

onHandleInput (cell's prop) is onChangeEditableCell (table's function)

PS

I need the data array to post the entire object when the user hits Save

Leandro Soares
  • 2,902
  • 2
  • 27
  • 39
  • Maybe I'm not following, but instead of modifying the state directly during "edit mode", why don't you modify a copy of the state and, when the user hits "save," just replace the whole object - or deep merge the two states? – Tyler Sebastian Mar 17 '17 at 16:54
  • Is it a good practice to create variables outside state? If that's the case, I'm going to search how to do it. It seems a better idea. – Leandro Soares Mar 17 '17 at 16:55
  • I'm not 100% sure - but it also seems excessive (and "dangerous") to stream changes to state and forcing unnecessary component re-rendering on every keystroke. – Tyler Sebastian Mar 17 '17 at 16:57
  • Yeah table-level state shouldn't change on every keypress. That kind of thing should live at the cell-level state. Then only when the save button is pressed should the table-level state update. – jered Mar 17 '17 at 17:00
  • I tought about that, but I'm always articles about "dumb" and "stateless" components that I try to do almost always. But about the "cell-level" state, how would I update the Table's state when the `Save` is hited? – Leandro Soares Mar 17 '17 at 17:02

2 Answers2

2

What I do in this situation is make the cell have its own state, that updates with each keypress. Then update the table-level state with the onblur event, which fires after the input loses focus.

Individual inputs are, in my opinion, a good exception to the general practice of pulling state upward.

Clarity
  • 86
  • 7
0

Try to add some timeout:

onChange(e) {
  e.preventDefault();
  const newValue = e.target.value;
  if (this.timeout) {
    clearTimeout(this.timeout);
    this.timeout = 0;
  }
  this.timeout = setTimeout(()=> {
    this.props.onHandleInput(this.props.field, this.props.rowIndex, newValue);
  }, 1000);

}
blackmiaool
  • 5,234
  • 2
  • 22
  • 39