【问题标题】:React event hierarchy issue反应事件层次结构问题
【发布时间】:2016-03-29 14:35:36
【问题描述】:

在深节点中处理状态更改的最佳方法是什么,也需要由父节点处理。这是我的情况:

<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 还是我错过了什么?

【问题讨论】:

    标签: javascript reactjs flux reactjs-flux


    【解决方案1】:

    所以,你只需要跟踪父组件中的状态,并与子组件共享状态更新功能:

    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>
        );
      }
    });
    

    希望这是有道理的。

    【讨论】:

    • 我支持这个。您应该努力将所有应用程序逻辑保留在最顶层的组件中,并让嵌套组件仅呈现其属性并在其中发生某些事情时触发事件,以便父级可以通过回调响应更改。
    • 谢谢!但问题是,我中间还有一个 Row 组件,这意味着将其传递 2 次。如果我应该创建另一个子组件,它将是 3 次,这些看起来真的很乏味。这是不是应该已经使用 Flux 之类的东西了?
    • 所以,首先,在上面使用的情况下,Row 实际上并不是Column 的父级,所以Row 不需要知道任何关于Column 的props .在 React 中,如果该组件直接呈现它的子组件,则该组件是另一个组件的父组件。因此,您可以拥有一个名为 DivMaker 的组件,其中包含 100 个嵌套 div,但所有这些 div 的父级都是 DivMaker,无论它们的嵌套深度如何。
    • 第二个问题更有趣。是的,最终它变得难以管理。 Flux 是一个不错的选择(我更喜欢 Reflux)。还请查看 React 的 context 功能,该功能专门用于减轻必须处理通过大型组件树传递道具的问题。
    猜你喜欢
    • 1970-01-01
    • 2011-03-12
    • 2011-01-18
    • 1970-01-01
    • 1970-01-01
    • 2017-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多