Почему мой дочерний компонент 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
непосредственно.