React顶层API
API | 描述 |
---|---|
React.Children | 用于操作 props.children |
React.cloneElement | 用于克隆一个 React 元素 |
React.isValidElement(obj) | 验证 obj 是否为 React 元素 |
React.lazy | |
React.Suspense |
React.Children
API | 描述 |
---|---|
React.Children.map | 加工 props.children 中的每个节点 |
React.Children.forEach | 遍历 props.children |
React.Children.count | 计算 props.children 的数量 |
React.Children.only | 判断 props.children 是否只有一个元素 |
React.Children.toArray | 将 props.children 转为数组并且扁平化 |
官方文档所说的 props.children
是一个不透明数据结构,本质上 props.children
可以是任何数据类型,比如你可以传入一个函数,不过这样是毫无意义的。
<Father>
{() => <div>hello</div>}
</Father>
这样在 Father 组件内部中 props.children
就是 () => <div>hello</div>
这个函数,如果我们依旧把它当作数组来处理,使用 props.children.map
,那么就会抛出一个 error,如果我们使用 React.Children.map
那么在任何情况下都不会报错,里面的 child 会忽略这个函数。
注意
- 使用组件时,如果它只嵌套了一个子节点,那么组件中的
props.children
表示的就是该子节点 - 如果组件有多个子节点,那么
props.children
就是一个数组
React.Children.forEach
React.Children.forEach(children, callback(child, index))
作用和 Array.prototype.forEach
相似,用来遍历 props.children
。
遍历过程中,对于 null/undefined/boolean
类型的 child
会被当作 null
。
React.Children.map
React.Children.map(children, callback(child, index))
作用和 Array.prototype.map
相似,用于加工 props.children
中的每一个元素。
const Father = (props) => {
return <div className="father">
{
React.Children.map(props.children, (child, index) => {
return (
<div>{child}{index}</div>
)
})
}
</div>;
};
React.Children.map
返回的数组会忽略掉 props.children
中的 null/undefined/boolean
类型的元素。
比如 props.children
的结构如下:
[
"hello",
undefined,
<div>123</div>,
true
]
经过如下处理:
const newChildren = React.Children.map(props.children, (child) => child);
newChildren = [
"hello",
<div>123</div>,
]
React.Children.count
React.Children.count(children)
获取 props.children
的长度。
你可以会疑惑为什么不直接使用 props.children.length
来获取子组件数量,因为前面我们说过 props.children
是不透明的数据结构,它可以是任何数据类型,如果子元素是一个字符串,那么我们使用 props.children.length
返回的就是字符串的字符长度,而 React.Children.count
会返回 1。
important
如果 props.children
是一个数组,使用该 API 时也会统计 undefined/null/boolean
类型的元素数量。
React.Children.only
React.Children.only(children)
验证 props.children
是否只有一个子节点(一个 React 元素),如果有则返回它,否则此方法会抛出错误。该方法用来限制组件必须只能有一个子组件。
function Father(props) {
return (
<div>{React.Children.only(props.children)}</div>
)
}
function App() {
// 如果传入了两个子组件,那么就会报错
return (
<Father>
<div>1</div>
<div>2</div>
</Father>
)
}
注意
React.Children.only()
不能接收来自 React.Children.map()
的返回值。
React.Children.toArray
可以把任何类型的 props.children
转换为数组并且将其 扁平化处理,其存在的目的也是为了增加容错。
<Father>
{"A"}
</Father>
Father 组件中具有一个子元素 "A",此时 Father 组件中 props.children
的取值就是 "A"
。
使用该 API 转换 props.children
后,返回值就变成了 ["A"]
。
function Father(props) {
const children = React.Children.toArray(props.children); // ["A"]
return <div>{children}</div>
}
注意
使用该方法转换 props.children
后,里面的 undefined/null/boolean
类型的元素会被过滤掉。
React.cloneElement
React.cloneElement(
element,
[config],
[...children]
)
用于克隆一个 React 元素,config 参数是一个对象,用于设置新的属性在新的 React 元素上,从第 3 个参数开始往后均为该元素的子元素,如果缺省则使用原来的子元素。
function Wrapper(props) {
console.log(props); // {children: Array(2), hello: 1}
return <></>
}
export default function App() {
const Ele = <Wrapper>123</Wrapper>;
const eleRef = React.createRef();
return (
<div className="App">
{React.cloneElement(Ele, { hello: 1, key: 1, ref: eleRef }, "1", "2")}
</div>
);
}