Skip to main content

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.toArrayprops.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>
);
}

React.lazy

React.Suspense