React.Children API
React.Children
提供了处理 this.props.children
这个不透明数据结构的工具。
map
React.Children.map
用于对 this.props.children
的每个子级进行遍历。
语法:
React.Children.map(children, function[(child, index)])
说明:
- 如果
children
是个内嵌的对象或者数组,他会被遍历,不会将对象或者数组传入到function
中。 - 如果
children
参数是null
或者undefined
,那么返回null
或者undefined
而不是一个空对象。 - 对数组进行扁平化处理,扁平化的过程中会忽略
null
或者undefined
,如果children
是
<>
{
[<span>1</span>,
<span>2</span>,
<span>3</span>,
[<span>4</span>, <span>5</span>],null,undefined];
}
</>
那么传入 function
的 child
就是
[
<span>1</span>,
<span>2</span>,
<span>3</span>,
<span>4</span>,
<span>5</span>,
];
this.props.children
的值有三种可能:
- 如果当前组件没有子节点,它就是
undefined
- 如果有一个子节点,数据类型是
object
- 如果有多个子节点,数据类型就是
array
其他方式
除了使用 React.Child.map
遍历, 还可以使用数组的 map
方法,但是使用数组方法操控 children
有 3 个问题:
- 用数组的方法需要声明
children
为ReactNode[]
类型,这样就必须传入多个元素才行,而React.Children
不用 - 用数组的方法不会对
children
做拍平,而React.Children
会 - 用数组的
sort()
方法不能做排序,因为children
的元素是只读的,而用React.Children.toArray
转成数组就可以了
当然,不用记这些区别,只要操作 children,就用 React.Children
的 api 就行了。
toArray
React.Children.toArray
可将 this.props.children
转换为数组,在这过程中,会扁平化所有嵌套数组,为每个子元素分配 key
。
语法:
React.Children.toArray(children);
代码示例:
class Sort extends React.Component {
render() {
const children = React.Children.toArray(this.props.children);
return <p>{children.sort().join(" ")}</p>;
}
}
<Sort>
{"bananas"}
{"oranges"}
{"apples"}
</Sort>
forEach
语法:
React.Children.forEach(children, function[(child, index)])
说明:
- 遍历
children
- 对每个子元素执行某些操作,但不改变或返回新的数据结构
例如:
- 打印日志
- 修改 DOM
- 触发事件
- 更新组件状态
示例:
React.Children.forEach(children, (child) => {
console.log(child.props); // 打印每个子元素的props
someExternalFunction(child); // 调用外部函数
if (child.type === "input") {
inputRefs.current.push(child); // 收集特定类型的子元素引用
}
});
这里,我们遍历了 children
,但没有创建新的数组或修改 children
本身。我们只是使用了每个 child
来执行一些"副作用"操作。
相比之下,Children.map
会创建并返回一个新数组,通常用于转换 children
。
count
React.Children.count
用于计算 this.props.children
中含有的节点数目。
由于 this.props.children
可以是任何类型的,因此检查一个组件有多少个 children
是非常困难的。
如果通过 this.props.children.length
判断字符串或函数时程序便会中断。
语法:
React.Children.count(children);
only
React.Children.only
限制 this.props.children
只能为单个 React 组件,否则将抛出错误。
语法:
React.Children.only(children);
最佳实践
改变属性
即便通过以前方法可以在子组件内部获得 this.props.children
以及其每个成员,但是要在子组件中改造 this.props.children
(例如添加 Props 属性等)则需要使用辅助方法 React.cloneElement
。
React.cloneElement
会克隆一个 React 元素,第一个参数为将要克隆的 React 元素,第二个参数则为想要为该克隆元素添加的属性。
renderChildren(){
return React.Children.map(this.props.children, (child, index) => {
return React.cloneElement(child, {
name: this.props.name,
number: this.state.number,
onChange: this.onChange,
})
})
}