为什么我的React子组件不接收新的道具?

时间:2017-10-03 15:25:49

标签: reactjs setstate react-lifecycle

我有一个充当可排序表的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触发componentWillReceivePropsshouldComponentUpdate第一次在父级触发setState,而不是第二次。

如果需要,我可以添加所有代码。这是一个错误吗?非常感谢任何帮助!

2 个答案:

答案 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