2015-12-23 116 views
7

什么是处理深层节点中状态更改的最佳方式,这也需要由父节点处理。这里是我的情况:React事件层次结构问题

<Table> 
 
    <Row prop={user1}> 
 
    <Column prop={user1_col1} /> 
 
    <Column prop={user1_col2} /> 
 
    </Row> 
 
    <Row prop={user2}> 
 
    <Column prop={user2_col1} /> 
 
    <Column prop={user2_col2} /> 
 
    </Row> 
 
    <TableFooter> 
 
    <FooterColumn prop={sum1} /> 
 
    <FooterColumn prop={sum2} /> 
 
    </TableFooter> 
 
</Table>

每当有人正在改变在列属性什么,我只需要该列组件内保持这个值的状态。但是,我现在想在FooterColumn组件中使用这些值的总和。达到此目的的最佳方法是什么?

如果我要抛弃状态改变,我必须在多个地方保持状态,然后将其传递下去,这是一项繁琐的工作。最好是使用EventEmitters还是我错过了一些东西?

回答

5

因此,所有你需要的是跟踪国家在父组件和共享状态更新功能,与孩子们:

var Parent = React.createClass({ 
    getInitialState: function() { 
    return { 
     users: [ 
     {name: 'Matt', values: [1, 2]}, 
     {name: 'user517153', values: [4, 5]} 
     ] 
    }; 
    }, 
    updateValue: function(rowId, colId, newValue) { 
    var newUsersState = this.state; 
    newUsersState.users[rowId].values[colId] = newValue; 
    this.setState({users: newUsersState}); 
    }, 
    render: function() { 
    var rows = this.state.users.map(function(user, r) { 
     var cols = user.values.map(function(value, c) { 
     return (
      <Column key={c} prop={value} rowId={r} colId={c} onChange={this.updateValue}/> 
     ); 
     }); 

     return (
     <Row key={r} prop={user}> 
      {cols} 
     </Row> 
    ); 
    }); 

    // Yes, it could be more efficient if you did it all in one map/forEach - doing this in a second one for clarity 
    var footerCols = this.state.users.map(function(user) { 
     var sum = 0; 
     user.values.forEach(function(value) { sum+= value; }); 
     return (
     <FooterColumn prop={sum} /> 
    ); 
    }); 

    return (
     <Table> 
     {rows} 
     <TableFooter> 
      {footerCols} 
     </TableFooter> 
     </Table> 
    ); 
    } 
}); 

在你Column类,你只需要沿着线的东西作者:

var Column = React.createClass({ 
    onChange: function(event) { 
    var props = this.props; 

    var newValue = event.target.value; // Get the new value somehow - this is just an example 
    props.onChange(props.rowId, props.coldId, newValue); 
    }, 
    render: function() { 
    var props = this.props; 

    return (
     <td onChange={this.onChnage}>{props.prop}</td> 
    ); 
    } 
}); 

希望是有道理的。

+0

我第二个这个。您应该努力将所有应用程序逻辑保留在最上面的组件中,并让嵌套组件只在其内发生某些事件时呈现其属性和触发事件,以便父级可以使用回调来响应这些更改。 – juandemarco

+0

谢谢!但事情是,我也有一个Row组件,这意味着将它传递给2次。如果我应该创建另一个子组件,它将是3次,这些看起来非常乏味。这是你应该已经使用Flux之类的地方吗? – user517153

+0

所以,首先,上面使用的“Row”实际上并不是“Column”的父项,因此“Row”不需要知道任何关于Column的道具。在React中,如果组件直接呈现子组件,则该组件是另一个组件的父组件。因此,您可以使用一个名为'DivMaker'的组件,其中包含100个嵌套div,但所有这些div的父组件都是'DivMaker',无论它们的嵌套深度如何。 –