Flux:从 JSX 中的子项触发父方法

Flux: Trigger parent methods from children in JSX

假设你有一个 Dropdown React 组件:

var Dropdown = React.createClass({
  render: function () {
    return (
      <div className="dropdown" />
    );
  },

  itemSelected: function (item) {
    this.setState({
      value: item.props.value
    });
  }
});

和对应的Option:

var Option = React.createClass({
  _onClick: function () {
    this.props.onSelect(this);
  },

  render: function () {
    return (
      <div className="item" onClick={this._onClick}>{this.props.value}</div>
    );
  }
});

现在假设您像这样一起使用这些组件:

var ColorForm = React.createClass({
  render: function () {
    return (
      <div>
        <label>Pick a color</label>
        <Dropdown>
          <Option onSelect={???.itemSelected} value="red" />
          <Option onSelect={???.itemSelected} value="blue" />
          <Option onSelect={???.itemSelected} value="green" />
        </Dropdown>
      </div>
    );
  }
});

注意 onSelect={???.itemSelected} 位。

如何将父级下拉列表的 itemSelected 方法传递给每个子级?

我知道如果我创建一个 自定义 下拉菜单 class,这很容易,但这违背了组件的目的:

var ColorDropdown = React.createClass({
  render: function () {
    return (
      <div className="dropdown">
        <Option onSelect={this.itemSelected} value="red" />
        <Option onSelect={this.itemSelected} value="blue" />
        <Option onSelect={this.itemSelected} value="green" />
      </div>
    );
  },

  itemSelected: function (item) {
    this.setState({
      value: item.props.value
    });
  }
});

您可以使用 this.props.childrenReact.Children.map 的组合将 onSelect 属性添加到 Dropdown::render 方法内的 child Option 元素, 和 React.cloneWithProps:

var React = require('react/addons');

var Option = require('./Option');

var Dropdown = React.createClass({

  itemSelected: function (item) {
    this.setState({
      value: item.value
    });
  },

  render: function () {
    var self = this;
    var children = React.Children.map(this.props.children, function (child) {
      if (child.type !== Option.type) {
        return child;
      } else {
        return Reat.cloneWithProps(child, {
          onSelect: function () {
            self.itemSelected(this);
          }
        });
      }
    });

    return (
      <div className="dropdown">
        {children}
      </div>
    );
  }
});

所以现在你不需要为每个 Item child 设置 onSelect:

var ColorForm = React.createClass({
  render: function () {
    return (
      <div>
        <label>Pick a color</label>
        <Dropdown>
          <Option value="red" />
          <Option value="blue" />
          <Option value="green" />
        </Dropdown>
      </div>
    );
  }
});

查看单选按钮的类似代码:http://jaketrent.com/post/send-props-to-children-react/