在github上编辑这篇文章

Keyed Fragments#

在大多数情况下,你可以使用 key prop 指定你从 render 返回的元素的 keys。然而,这在一个情况下会失败:如果你有两组你需要记录的子级,将没有办法在不使用包裹元素的情况下放置一个 key 到每组上。

即是,如果你有一个像这样的组件:

var Swapper = React.createClass({
  propTypes: {
    // `leftChildren` and `rightChildren` can be a string, element, array, etc.
    leftChildren: React.PropTypes.node,
    rightChildren: React.PropTypes.node,

    swapped: React.PropTypes.bool
  },
  render: function() {
    var children;
    if (this.props.swapped) {
      children = [this.props.rightChildren, this.props.leftChildren];
    } else {
      children = [this.props.leftChildren, this.props.rightChildren];
    }
    return <div>{children}</div>;
  }
});

这些子级会在当你改变 swapped prop 时加载和卸载,因为没有任何的 key 标记在这两组子级上。

要解决这个问题,你可以使用 createFragment 插件来给予这两组子级 keys.

Array<ReactNode> createFragment(object children)#

代替创建数组,我们这样写:

var createFragment = require('react-addons-create-fragment');

if (this.props.swapped) {
  children = createFragment({
    right: this.props.rightChildren,
    left: this.props.leftChildren
  });
} else {
  children = createFragment({
    left: this.props.leftChildren,
    right: this.props.rightChildren
  });
}

被传入对象的 keys (即 leftright)被用作为整组子级的 keys,并且对象 keys 的顺序被用于决定渲染子级的顺序。通过这个改变,这两个子级将会恰当的在 DOM 里排序,而不被卸载。

createFragment 的返回值应该被对待为一个不透明的对象;你可以使用 React.Children 来遍历一个 fragment 但是不应该直接访问它。同样注意,我们依赖于 JavaScript 引擎保留了对象的枚举顺序,这点在 spec 上是不保证的,但是所有主要的浏览器和 VMs 都对非数字键的对象实现了这个特性。

注意:

将来,createFragment 也许会被替换为如下的API:

return (
  <div>
    <x:frag key="right">{this.props.rightChildren}</x:frag>,
    <x:frag key="left">{this.props.leftChildren}</x:frag>
  </div>
);

允许你直接在 JSX 里赋值 keys 而不用添加包裹元素。