React:高阶组件中的嵌套可重用组合组件

时间:2016-06-09 05:36:15

标签: reactjs components composite-component higher-order-functions

我一直试图绕过这个问题一段时间。我已经破解了一个有效的解决方案,直到我得到任何嵌套的div,然后事情就崩溃了。基本上我要做的是创建生活在更高阶组件中的组合组件,并且所有组件都共享相同的当前状态。然后我需要导出它,以便任何文件都可以使用这些组件。所以这就是JSX的样子:

<Panel countersStartAt=5>
  <Counter incrementsBy=1 />
  <div>
    <Counter incrementsBy=2 />
  </div>
  <TotalCounter className="someclass" />
</Panel>

所以我希望这样的方式工作的方式是我有这个包装器Panel组件设置一些初始状态,比如this.state.start = 5.在Panel中,Counter组件将有一个onClick处理程序,增加状态.start by incrementmentsBy。而TotalCounter将是一个显示state.start的组件。当然这是一个人为的例子,所以如果不提出如何使这个特定的组件变得更好,将会有所帮助。我希望将此应用于更现实的情况。

第二件事是如何以一种我可以在无状态组件中的单独文件中创建上面的确切代码的方式导出这些组件。希望这是有道理的。

这是我正在做的事情的片段。

  renderChildren = (children) => {
    return React.Children.map(children, (child) => {
      if (React.isValidElement(child)) {
        return React.createElement(
          (child.type.name ? this[child.type.name] : child.type),
          child.props
        );
      }
      return child;
    });
  };

  render = () => {
    return (
        {this.renderChildren(this.props.children)}
    )
  };

然后在Panel类之外,我这样导出:

export const Counter = () => null;

就这样暴露了Counter。默认呈现null不会发生,因为我将Panel替换为Panel中的this.Counter()方法。

在评论及其他事项中提出的问题需要考虑

  • 我没有使用Flux或Redux
  • 假设Panel代码段用于多个不实现Flux模式或Redux的项目中的几种渲染方法
  • 假设无法重写这些代码段
  • 如何导出Panel,Counter和TotalCounter?是否可以为Counter和TotalCounter执行此操作,因为它们是Panel类中的方法?我的研究导致没有,并创建要导出的“虚拟”组件,以便当前文件可以正确使用它们。

1 个答案:

答案 0 :(得分:1)

在这里为我们在聊天室讨论的内容提供答案

如果没有像Redux或Flux这样的数据管理框架,处理你想要做的事情的最佳方法是将你的数据作为道具传递,就像这样。

class Panel extends Component {

    constructor(){
      super()
      this.state = {count: 5}
    }
    incrementCount = (incrementer) => {
      this.setState({count: this.state.count + incrementer});
    }
    render (){
      return (
        <div>
          <Counter incrementCount={this.incrementCount} count={this.state.count} incrementsBy=2 />
        </div>
      );
    }

}

然后在你的柜台..

<someElement onClick={ (e) => {this.props.incrementCount(this.props.incrementsBy)} }>{this.props.count}</someElement>