我有一个充当可排序表的React组件。表头和表行是容器的子项,容器正在处理表的状态。单击标题时,数据将重新排序,就像在this semantic-ui-react example中一样。
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>
)
}
Here's a video of this in action.
在视频中,您可以看到OverviewTableRows
触发componentWillReceiveProps
和shouldComponentUpdate
第一次在父级触发setState
,而不是第二次。
如果需要,我可以添加所有代码。这是一个错误吗?非常感谢任何帮助!
答案 0 :(得分:1)
我通过在反转它并使用它来更新状态之前复制数组来解决这个问题。
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的功能性有关。我希望这有助于某人!如果有人对这种情况有充分的解释,我很乐意听到它。
答案 1 :(得分:0)
这是一个很好的引用,可以解释发生了什么。
通过直接操作this.state,你可以绕过React的状态管理,这可能有潜在危险,因为之后调用setState()可能会替换你所做的突变。
取自this article。
由于orders
是一个可变对象和state
的成员,因此当您调用orders.reverse
时,您正在直接改变状态(即使此重新排序是在{{1}内完成的调用)。
所以,是的,您创建setState
副本的解决方案将解决此问题,因为您不再直接更改orders
。