我有以下代码,但无法编译:
import React, {PropsWithChildren} from "react";
import useScrollTrigger from "@material-ui/core/useScrollTrigger";
export default function ElevationScroll({children}: PropsWithChildren<{}>) {
const trigger = useScrollTrigger({
disableHysteresis: true,
threshold: 0
});
return React.cloneElement(children, {
elevation: trigger ? 3 : 0,
});
错误信息:
The last overload gave the following error.
Argument of type 'ReactNode' is not assignable to parameter of type 'ReactElement<any, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<any, any, any>)>'.
Type 'undefined' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<any, any, any>)>'. TS2769
10 | });
11 |
> 12 | return React.cloneElement(children, {
| ^
13 | elevation: trigger ? 3 : 0,
14 | });
15 | }
看ReactNode
的类型定义:
type ReactChild = ReactElement | ReactText;
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
ReactNode
也可以是 ReactElement
。
但是为什么 React.cloneElement
不接受 children
?
更新
我将如何使用 ElevationScroll
:
<ElevationScroll>
<AppBar color="default" elevation={0} classes={{colorDefault: classes.appBar}}>
<Container maxWidth="lg">
<Toolbar className={classes.toolbar}>
<img alt="logo" src={logo} className={classes.logo}/>
</Toolbar>
</Container>
</AppBar>
</ElevationScroll>
如您所见,它只包含一个孩子。
我更改了 ElevationScroll
的实现:
export default function ElevationScroll({children}: PropsWithChildren<{}>) {
const trigger = useScrollTrigger({
disableHysteresis: true,
threshold: 0
});
return React.cloneElement(React.Children.only(children), {
elevation: trigger ? 3 : 0,
});
}
编译器仍然抱怨:
No overload matches this call.
The last overload gave the following error.
Argument of type 'string | number | boolean | {} | ReactElement<any, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<any, any, any>)> | ReactPortal | null | undefined' is not assignable to parameter of type 'ReactElement<any, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<any, any, any>)>'.
Type 'undefined' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<any, any, any>)>'. TS2769
11 |
12 |
> 13 | return React.cloneElement(React.Children.only(children), {
| ^
14 | elevation: trigger ? 3 : 0,
15 | });
16 | }
我也试过:
export default function ElevationScroll({children}: PropsWithChildren<{}>) {
const trigger = useScrollTrigger({
disableHysteresis: true,
threshold: 0
});
return React.Children
.map(children, (ele) => React.cloneElement(ele, {
elevation: trigger ? 3 : 0,
}));
}
编译器抱怨:
The last overload gave the following error.
Argument of type 'ReactNode' is not assignable to parameter of type 'ReactElement<any, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<any, any, any>)>'.
Type 'undefined' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<any, any, any>)>'. TS2769
12 |
13 | return React.Children
> 14 | .map(children, (ele) => React.cloneElement(ele, {
| ^
15 | elevation: trigger ? 3 : 0,
16 | }));
17 | }
答案 0 :(得分:2)
您不能提供 ReactNode
(children
类型)作为 ReactElement
。问题是 ReactNode
还包括片段、普通文本和其他原始值。你必须事先施放它(不太好)或(更好)仔细检查你的孩子
如果您只想抚养一个孩子 - 使用 Children.only
。
如果您想克隆多个元素 - 使用 Children.map
。
如果你想支持片段,你还应该检查给定的元素是否是一个片段,然后做任何你想做的事情——忽略它,改用它的子元素。
在此处阅读有关 Children
实用程序的更多信息:https://reactjs.org/docs/react-api.html#reactchildren