React
React.Children.map
React.Children.map 用来安全遍历 children,并给每个子节点做包装处理。之所以需要它,是因为 React 的 children 不一定是数组——直接调 .map() 会报错。
Children.map 内部会自动规范化 children:单个节点、数组、字符串、null 都能正确处理。
一、为什么不能直接用 children.map
children 可能是以下任何一种情况,只有数组才有 .map() 方法:
| children 值 | typeof | 能直接 .map() |
|---|---|---|
<div />(单个) | object | ❌ |
[<A/>, <B/>] | array | ✅ |
'hello'(字符串) | string | ❌ |
null | object(null) | ❌ |
undefined | undefined | ❌ |
所以 React 提供了 React.Children.map,等价于先在内部做了一层规范化:
// 粗暴等价理解(React 内部实现更复杂,会额外处理 key、Fragment、null)
const safeChildren = Array.isArray(children) ? children : [children]
safeChildren.map((child) => {
/* ... */
})二、核心示例
下面是一个典型的 RowList 组件,给每个 children 外面包一层 <div class="row">:
import { Children } from 'react'
function RowList({ children }) {
return (
<div>
{Children.map(children, (child) => (
<div className="row">{child}</div>
))}
</div>
)
}使用时:
function Demo() {
return (
<RowList>
<span>A</span>
<span>B</span>
</RowList>
)
}渲染结果为每个 <span> 外层包一层 <div class="row">:
<div>
<div class="row"><span>A</span></div>
<div class="row"><span>B</span></div>
</div>三、常用 API
React.Children 提供 5 个静态方法:
| API | 作用 |
|---|---|
Children.map | 遍历 children,对每个子节点做转换并返回新数组 |
Children.forEach | 仅遍历,不返回新数组 |
Children.count | 统计 children 数量(null/undefined 计为 0) |
Children.only | 验证只有一个子元素,否则抛错;常用于单子组件 |
Children.toArray | 将 children 转换为真正的数组,并自动处理 key 去重 |
四、使用场景
现在写业务代码时,大多数情况下直接渲染 {children} 就够了。Children.map 主要用在组件库和插槽封装中,比如 Tabs、Form、Menu、Table、Layout 等需要统一给 children 添加属性或包装 DOM 的场景。
五、面试总结
面试时可以这样回答:
React.Children.map用于安全遍历children。因为 children 可能是单个元素、字符串或 null,不存在.map()方法。Children.map内部做了规范化处理,即便是单个 child 也能正常遍历。典型用法是给每个 children 外层包一层容器——本质是一个安全的children包装函数。