何时使用React createFragment?

Hen*_*Zhu 17 reactjs react-native

我正在使用ListViewReact Native 渲染,设法修复此React警告,但我不明白它是如何工作的原因:

警告:在作为子对象传递之前,对任何键控对象的使用都应该包装在React.addons.createFragment(object)中.

// This array generates React Fragment warning.
var data1 = [{name: "bob"}, {name:"john"}]

// This array works, no warnings.
var data2 = [React.addons.createFragment({name: "bob"}),
             React.addons.createFragment({name: "john"})]

// This also works, no warnings.
var data3 = ["bob", "john"]

class Listings extends React.Component {
  constructor(props) {
    super(props)
    ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2})

    this.state = {
      dataSource: ds.cloneWithRows(data),
    }
  }
  render() {
    return (
       <ListView
         dataSource={this.state.dataSource} 
         renderRow={(rowData) => <Text>{rowData}</Text>} />
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

什么是反应片段?React什么时候需要?为什么键控对象会导致此警告?

Kal*_*sev 16

我将我的答案分为两部分,以涵盖我在你的问题中看到的两个要点.

第1节:什么是反应片段?

为了解释React Fragment是什么,我们需要退一步并讨论React Keys.

密钥帮助React识别哪些项目已更改,已添加或已删除.它们应该被赋予数组内的元素,以赋予元素稳定的标识(唯一性).

选择密钥的最佳方法是使用在其兄弟姐妹中唯一标识列表项的字符串.大多数情况下,您会使用数据中的ID作为键.这是一个实际的例子:

render() {
    const todoItems = todos.map((todo) =>
      <li key={todo.id}>
        {todo.text}
      </li>
    );

    return todoItems;
}
Run Code Online (Sandbox Code Playgroud)

重要的todoItems是要注意,它实际上是一个<li>元素数组.

知道了,让我们继续讨论为什么在用例中收到警告.

在大多数情况下,您可以使用keyprop来指定从渲染返回的元素上的键,就像上面的示例一样.但是,在一种情况下会出现这种情况:如果您有两组需要重新排序的子项,则无法在不添加包装元素的情况下在每个组上放置键.

以下是最近更新的React文档中的经典示例:

function Swapper(props) {
  let children;
  if (props.swapped) {
    children = [props.rightChildren, props.leftChildren];
  } else {
    children = [props.leftChildren, props.rightChildren];
  }
  return <div>{children}</div>;
}
Run Code Online (Sandbox Code Playgroud)

当您更换swapped道具时,孩子们将卸下并重新安装,因为两组孩子上没有标记任何钥匙.

要解决此问题,可以使用createFragment加载项为子集提供密钥.按照增强的示例,使用createFragment此处.


第2节:但为什么你会收到这个警告?

无论如何,您收到错误的错误只是因为您尝试将JavaScript对象(而不是JSX元素或字符串)插入到某些JSX中.

虽然错误消息建议createFragment用来解决这个问题,但原因是你将一个变量插入到一个不是字符串或JSX元素的JSX中,但实际上是其他类型的对象!

你的用例中有这种误导性的警告,不是吗?:-)