Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

All table rows re-render after selection changes

Tags:

reactjs

mobx

I have table of customers and the selected customer is stored in the ViewState. The problem is that all rows re-render when the selection changes which is quite slow. Ideally only the selected row and the row previously selected would re-render, but I did not find out how to achieve this. My structure is identical to the example in the MobX contact list example:

{this.filteredCustomers.map(customer => {
   return (
      <CustomerRow
         key={customer.id}
         customer={customer}                    
         viewState={this.props.store.view}
      />
   )                
})}

and

const CustomerRow = observer((props: CustomerRowProps) => {
   const isSelected = props.viewState.isCustomerSelected(props.customer)
   const rowClass = isSelected ? 'active' : ''

   return (
     <tr className={rowClass}>
       <td>{props.customer.lastName}</td>
       <td>{props.customer.firstName}</td>
     </tr>
   )
})

All rows depend on the value of ViewState.selectedCustomer through the isCustomerSelected method.

Is there another way to structure this that avoids re-rendering all rows?

like image 687
jpfollenius Avatar asked Aug 26 '17 10:08

jpfollenius


People also ask

How to redraw the table after submit event?

In your submit event handler use row ().data () to update the row's data then draw () to redraw the table. I tried doing with row ().data () , but i am actually creating cells in columns using createdcell (). They are not getting used. It is updating with normal values instead of the values from createdCell

How to refresh the table after saving a row?

You will need to send the row to the server to save in then DB then use draw () or ajax.reload () to refresh the table. Client side : Since i have to send multiple rows data on click of another button, with normal datatables ,i wanted to re-render only one row , the data for that row is in client side on clicking of row's save button.

Is it possible to update the table without draw event?

I believe you can update the table display using row ().data () without the draw () but none of the callbacks, like rowCallback, will run without a draw event. Here is an example of why this is a problem. A user updates a row and the code displays it using row ().data (). The user searches or sorts the table. The updated data is now gone.

Will rowcallback() gets called on row data draw()?

2.will rowcallback () gets called on row ().data ().draw ()---- but on using this it is actually making a call to the server (for server side) As we said if you are using server side processing you need to update the data in your server database then use draw () to fetch the updated row data.


2 Answers

The reason why all the rows are re-rendered is because props.viewState.isCustomerSelected(props.customer) has to be re-evaluated for each observer component when the used observable change.

One way to get around this is to use a map so that every entry will have a potential checked field of their own, so that only the selected and deselected components have to re-render.

Example (JSBin)

class AppState {
  @observable todos = [
    {
      id: '1',
      title: 'Do something'
    }, 
    {
      id: '2',
      title: 'Do something else'
    },
    {
      id: '3',
      title: 'Do a third thing'
    }
  ]

}

var appState = new AppState();

@observer
class Todos extends React.Component {
  checked = observable.map({});

  changeTodo = (todo) => {
    this.checked.clear();
    this.checked.set(todo.id, true);
  };

  render() {
    return <div>
      <ul>
        { this.props.appState.todos.map((todo) =>
          <Todo 
            todo={todo} 
            key={todo.id}
            checked={this.checked}
            onChange={() => this.changeTodo(todo)} />
        ) }
      </ul>
      <DevTools />
    </div>;
  }
}

@observer
class Todo extends React.Component {
  render() {
    const { todo, checked, onChange } = this.props;
    const isChecked = checked.get(todo.id);
    return <li>
      <input 
        type="checkbox"
        checked={isChecked} 
        onChange={onChange} />
      {todo.title}
    </li>;
  }
}
like image 173
Tholle Avatar answered Oct 25 '22 02:10

Tholle


You can use shouldComponentUpdate to deside wheather component updates or not.

like image 36
bennygenel Avatar answered Oct 25 '22 03:10

bennygenel