相关文章推荐

陷阱

使用 Children 不常见,并可能导致代码脆弱。 查看常见替代方案。

Children 允许你操作和转换作为 children 属性 接收到的 JSX。

const mappedChildren = Children.map(children, child =>
<div className="Row">
{child}
</div>
);

Children.count(children)

调用 Children.count(children) 来计算 children 数据结构中的子元素数量。

import { Children } from 'react';

function RowList({ children }) {
return (
<>
<h1>Total rows: {Children.count(children)}</h1>
...
</>
);
}

请参见下面的更多示例。

  • children : 你的组件收到的 children 属性 的值。
  • 这些 children 内的节点数量。

  • 空节点( null 、 undefined 和布尔值)、字符串、数字和 React 元素 计为单个节点。数组不计为单个节点,但其子元素计为单个节点。 遍历不会深入到 React 元素中: 它们不会被渲染,它们的子元素也不会被遍历。 碎片 不会被遍历。
  • Children.forEach(children, fn, thisArg?)

    调用 Children.forEach(children, fn, thisArg?) 对 children 数据结构中的每个子元素运行一些代码。

    import { Children } from 'react';

    function SeparatorList({ children }) {
    const result = [];
    Children.forEach(children, (child, index) => {
    result.push(child);
    result.push(<hr key={index} />);
    });
    // ...

    请参见下面的更多示例。

  • children : 你的组件收到的 children 属性 的值。
  • fn :您希望为每个子元素运行的函数,类似于 数组 forEach 方法 的回调函数。它将以子元素作为第一个参数,其索引作为第二个参数被调用。索引从 0 开始,每次调用递增。
  • 可选 thisArg : this 值 , fn 函数应该以此值来调用。如果省略,则为 undefined 。
  • Children.forEach 返回 undefined 。

  • 空节点( null 、 undefined 和布尔值)、字符串、数字和 React 元素 计为单个节点。数组不计为单个节点,但其子元素计为单个节点。 遍历不会深入到 React 元素中: 它们不会被渲染,它们的子元素也不会被遍历。 碎片 不会被遍历。
  • Children.map(children, fn, thisArg?)

    调用 Children.map(children, fn, thisArg?) 对 children 数据结构中的每个子元素进行映射或转换。

    import { Children } from 'react';

    function RowList({ children }) {
    return (
    <div className="RowList">
    {Children.map(children, child =>
    <div className="Row">
    {child}
    </div>
    )}
    </div>
    );
    }

    请参见下面的更多示例。

  • children : 你的组件收到的 children 属性 的值。
  • fn :映射函数,类似于 数组 map 方法 的回调函数。它将以子元素作为第一个参数,其索引作为第二个参数被调用。索引从 0 开始,每次调用递增。您需要从此函数返回一个 React 节点。这可以是空节点( null , undefined 或布尔值)、字符串、数字、React 元素或其他 React 节点的数组。
  • 可选 thisArg : this 值 , fn 函数应该以此值来调用。如果省略,则为 undefined 。
  • 如果 children 为 null 或 undefined ,则返回相同的值。

    否则,返回一个扁平数组,该数组包含您从 fn 函数返回的节点。返回的数组将包含您返回的所有节点,除了 null 和 undefined 。

    空节点( null 、 undefined 和布尔值)、字符串、数字和 React 元素 计为单个节点。数组不计为单个节点,但其子元素计为单个节点。 遍历不会深入到 React 元素中: 它们不会被渲染,它们的子元素也不会被遍历。 碎片 不会被遍历。

    如果您从 fn 返回带有键的元素或元素数组, 则返回元素的键将自动与来自 children 的相应原始项的键合并。 当您从 fn 中以数组形式返回多个元素时,它们的键只需要在彼此之间局部唯一。

    Children.only(children)

    调用 Children.only(children) 来断言 children 代表单个 React 元素。

    function Box({ children }) {
    const element = Children.only(children);
    // ...
  • children : 你的组件收到的 children 属性 的值。
  • 如果 children 是有效的元素 ,则返回该元素。

    否则,抛出错误。

  • 此方法如果将数组(例如 Children.map 的返回值)作为 children 传递,则始终会 抛出异常。 换句话说,它强制要求 children 是单个 React 元素,而不是包含单个元素的数组。
  • Children.toArray(children)

    调用 Children.toArray(children) 来根据 children 数据结构创建一个数组。

    import { Children } from 'react';

    export default function ReversedList({ children }) {
    const result = Children.toArray(children);
    result.reverse();
    // ...
  • children : 你的组件收到的 children 属性 的值。
  • 返回 children 中元素的扁平数组。

  • 空节点( null 、 undefined 和布尔值)将在返回的数组中被忽略。 返回元素的键将根据原始元素的键及其嵌套级别和位置计算。 这确保了扁平化数组不会改变行为。
  • 转换子元素

    要转换组件 作为 children 属性接收的子元素 JSX ,请调用 Children.map

    import { Children } from 'react';

    function RowList({ children }) {
    return (
    <div className="RowList">
    {Children.map(children, child =>
    <div className="Row">
    {child}
    </div>
    )}
    </div>
    );
    }

    在上例中, RowList 会将其接收到的每个子元素都包装在一个 <div className="Row"> 容器中。例如,假设父组件传递三个 <p> 标签作为 children 属性传递给 RowList

    < RowList>
    <p>This is the first item.</p>
    <p>This is the second item.</p>
    <p>This is the third item.</p>
    </RowList>

    然后,使用上面的 RowList 实现,最终渲染结果如下所示

    <div className="RowList">
    <div className="Row">
    <p>This is the first item.</p>
    </div>
    <div className="Row">
    <p>This is the second item.</p>
    </div>
    <div className="Row">
    <p>This is the third item.</p>
    </div>
    </div>

    Children.map 类似于 使用 map() 转换数组。 区别在于 children 数据结构被认为是 *不透明的*。这意味着即使它有时是数组,也不应该假设它是数组或任何其他特定数据类型。这就是为什么如果需要转换它,应该使用 Children.map 。

    import { Children } from 'react';
    export default function RowList({ children }) {
      return (
        <div className="RowList">
          {Children.map(children, child =>
            <div className="Row">
              {child}
            </div>
        </div>
    
    深入探讨

    为什么 children 属性并不总是数组?

    在 React 中,children 属性被认为是不透明的数据结构。这意味着你不应该依赖它的结构。要转换、过滤或计数子元素,应该使用 Children 方法。

    实际上,children 数据结构通常在内部表示为数组。但是,如果只有一个子元素,那么 React 不会创建额外的数组,因为这会导致不必要的内存开销。只要使用 Children 方法而不是直接检查 children 属性,即使 React 更改了数据结构的实际实现方式,你的代码也不会中断。

    即使 children 是一个数组,Children.map 也有有用的特殊行为。例如,Children.map 将返回元素上的 键 与你传递给它的 children 上的键组合起来。这确保了即使像上例一样被包装,原始的 JSX 子元素也不会“丢失”键。

    陷阱

    children 数据结构不包含你作为 JSX 传递的组件的渲染输出。在下例中,RowList 收到的 children 只包含两个项目,而不是三个

    1. <p>这是第一个项目。</p>
    2. <MoreRows />

    这就是为什么在这个例子中只生成两个行包装器的原因

    import RowList from './RowList.js';
    export default function App() {
      return (
        <RowList>
          <p>This is the first item.</p>
          <MoreRows />
        </RowList>
    function MoreRows() {
      return (
          <p>This is the second item.</p>
          <p>This is the third item.</p>
    
     
    推荐文章