После повторного изменения всех строк таблицы

У меня есть таблица клиентов, и выбранный клиент хранится в ViewState. Проблема в том, что все строки перерисовываются, когда выбор изменяется довольно медленно. В идеале, только выбранная строка и выбранная строка будут повторно отображены, но я не узнал, как этого добиться. Моя структура идентична примеру в Пример списка контактов MobX:

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

и

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>
   )
})

Все строки зависят от значения ViewState.selectedCustomer с помощью метода isCustomerSelected.

Есть ли другой способ структурировать это, что позволяет избежать повторного рендеринга всех строк?

Ответ 1

Вы можете использовать shouldComponentUpdate, чтобы обновлять обновления компонентов или нет.

Ответ 2

Причина, по которой все строки перерисовываются, заключается в том, что props.viewState.isCustomerSelected(props.customer) необходимо переоценить для каждого компонента наблюдателя при использовании наблюдаемого изменения.

Один из способов обойти это - использовать map, чтобы каждая запись имела потенциал checked, так что только выделенные и невыбранные компоненты должны быть повторно отображены.

Пример (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>;
  }
}