Почему мой дочерний компонент React не получает новые реквизиты?

У меня есть компонент React, который действует как сортируемая таблица. Заголовок таблицы и строки таблицы являются дочерними элементами контейнера, и контейнер обрабатывает состояние таблицы. При щелчке по заголовку данные переупорядочиваются так же, как и в этом примере семантического интерфейса.

handleSort = (clickedColumn) => {
const { column, orders, direction } = this.state

if (column !== clickedColumn) {
  this.setState({
    column: clickedColumn,
    orders: customSort(orders, clickedColumn),
    direction: 'ascending',
  })
} else {
this.setState({
  orders: orders.reverse(),
  direction: direction === 'ascending' ? 'descending' : 'ascending',
})}

При первом щелчке по заголовку столбца выполняется первое закрытие и this.setState изменяет состояние контейнера и запускает дочерние элементы для получения новых реквизитов и обновления соответственно. Если я повторно щелкну заголовок столбца, чтобы изменить порядок данных, будет выполнено второе закрытие и this.setState обновляет состояние контейнера. Соответственно, дочерний компонент OverviewTableHeader обновления, но OverviewTableRows не.

render() {
const { designers, orders, column, direction } = this.state
if (orders === "loading"){
  return <Loading />
} 
const tableRows = <OverviewTableRows  
                     designers={designers} 
                     orders={this.state.orders}
                     />
debugger
return (
  <div className="overview">
    <Table selectable fixed sortable>
      <OverviewTableHeader sort={this.handleSort} column={column} direction={direction}/>
      {tableRows}
    </Table>
  </div>
  ) 
}

Вот видео этого в действии.

На видео вы можете увидеть OverviewTableRows спусковой крючок componentWillReceiveProps а также shouldComponentUpdate первый раз setState срабатывает у родителя, а не у второго.

Я могу добавить весь свой код, если это необходимо. Это ошибка? Любая помощь очень ценится!

2 ответа

Я решил эту проблему, сделав копию массива, прежде чем развернуть его и использовать для обновления состояния.

handleSort = (clickedColumn) => {
const { column, orders, direction } = this.state

if (column !== clickedColumn) {
  this.setState({
    column: clickedColumn,
    orders: customSort(orders, clickedColumn),
    direction: 'ascending',
  })
} else {
  const reversedOrders = orders.slice().reverse();
this.setState({
  orders: reversedOrders,
  direction: direction === 'ascending' ? 'descending' : 'ascending',
})}

Я думаю, идентичность массива orders имело значение. Я предполагаю, что это связано с функциональной природой React. Надеюсь, это кому-нибудь поможет! Если у кого-нибудь есть хорошее объяснение, почему это так, я бы хотел услышать это.

Вот хорошая цитата, которая может объяснить, что происходит.

Управляя this.state напрямую, вы обходите управление состоянием React, которое может быть потенциально опасным, так как последующий вызов setState() может заменить сделанную вами мутацию.

Взято из этой статьи.

поскольку orders является изменяемым объектом и членом state, вы меняете состояние напрямую, когда звоните orders.reverse (даже если это изменение порядка выполняется в течение setState вызов).

Так что, да, ваше решение о создании копии orders решит эту проблему, потому что вы больше не изменяете this.state непосредственно.

Другие вопросы по тегам