export const PageViewTracker = ({ children }: ReactNode): ReactElement => {
usePageView();
return children;
};
问题:
此函数返回错误 »属性'子项'在类型'ReactNode'«上不存在
我的解决方案:
我尝试了几种类型,但只有任何不是我想要的作品。通常我使用ReactNode作为儿童道具,它工作得很好。在这种情况下,TypeScript 似乎有问题。
React>=18
在 React 18 中,FunctionalComponent
接口已更改为:
interface FunctionComponent<P = {}> {
(props: P, context?: any): ReactElement<any, any> | null;
propTypes?: WeakValidationMap<P> | undefined;
contextTypes?: ValidationMap<any> | undefined;
defaultProps?: Partial<P> | undefined;
displayName?: string | undefined;
}
请注意,在 React 18 之后,FunctionalComponent 的props
类型省略了PropsWithChildren
类型,这意味着您必须自己包含children
道具:
interface Props {
children: React.ReactNode;
}
export const PageViewTracker: React.FC<Props> = ({ children }) => {
}
他们删除隐式children
道具的原因可以在这里找到。(来源于 React 18 的类型定义发行说明(。
PropsWithChildren
类型在 React 的类型中仍然可用,所以如果你仍然想像 React 18 之前的版本一样选择children
作为道具,你仍然可以这样做:
import { PropsWithChildren } from 'react';
interface Props {
foo: string;
}
export const PageViewTracker: React.FC<PropsWithChildren<Props>> = ({ children, foo }) => {
}
PropsWithChildren
的类型定义为:
type PropsWithChildren<P = unknown> = P & { children?: ReactNode | undefined };
<小时 />反应 <=17
您收到该错误的原因是因为您将"ReactNode"接口提供给对象({}: Type
(。children
本身的类型为 ReactNode:
type PropsWithChildren<P> = P & { children?: ReactNode };
您应该为您的PageViewTracker提供FunctionComponent
(或其别名FC
(类型。
export const PageViewTracker: React.FC = ({ children }) => {
...
}
它具有以下界面:
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement | null;
propTypes?: WeakValidationMap<P>;
contextTypes?: ValidationMap<any>;
defaultProps?: Partial<P>;
displayName?: string;
}
因此,默认情况下,它接受类型为"ReactNode"的children
prop。
重要说明:在 react 18.0.0 之后,它们会让你在每个 FC 接口中包含子项。
interface MyButtonProps {
color: string;
children?: React.ReactNode;
}
然后你可以像旧版本一样传递道具。
const Button:React.FC<MyButtonProps> = (props) => {
//use children with {props.children} just like before
}
从文档
对于"@types/反应":"17.0.43",或小于 18
import { FunctionComponent } from "react";
const BaseLayout: FunctionComponent = ({ children }) => {
return (
<>
</>
);
};
export default BaseLayout;
对于"@types/反应"> 18
interface BaseLayoutProps {
children?: ReactNode;
}
const BaseLayout: FunctionComponent<BaseLayoutProps> = ({ children }) => {
return (
<>
</>
);
};
但在某些情况下,您仍然需要使用FunctionComponent
.例如:
interface ArtListProps {
arts: Art[];
children: FunctionComponent;
}
export default function ArtList({ arts, children }: ArtListProps) {
return (
<section className="grid md:grid-cols-1 lg:grid-cols-2 gap-4 mb-5">
{/* this is called render prop */}
{arts.map((art) => children(art))}
</section>
);
}
如果您传递ReactNode
,则会收到错误"类型ReactNode不可调用">
你可以简单地这样写:
export const PageViewTracker = ({ children }: {children: ReactNode}): ReactElement => {
usePageView();
return children;
};
请注意,我将({ children }: ReactNode)
更改为({ children }: {children: ReactNode})
import React from 'react';
interface Props {
children?: React.ReactNode;
}
export const MenuLateral: React.FC<Props> = ({ children }) => {
return (
<>
{children}
</>
);
};
正如丹在他的一条推文中提到的, "如果您在将 @types/react 升级到 18.0.0 时收到有关children
prop 的 TypeScript 错误,修复程序如下所示。你需要在 props 类型中将它们声明为常规道具,并使用 React.ReactNode 类型。
反应 18
你可以在这里查看他的推文:https://twitter.com/dan_abramov/status/1512833611401150474
或此处的堆栈溢出线程: React 18 TypeScript children FC
你可以试试这个:
import { ReactNode } from "react";
export const PageViewTracker= ( { children }: {children: ReactNode} ) => {
usePageView();
return children;
};
您可以在泛型类型参数中批注它的类型:
import React, {ReactNode} from "react";
const Hello: React.FC<{ children: ReactNode }> = ({children}) => {
return <React.Fragment>
Hello {children}
</React.Fragment>;
}
import Navbar from "../Navbar/Navbar";
interface Layout {
children?: ReactNode;
}
const Layout: React.FC<Layout> = ({ children }) => {
return (
<>
<Navbar />
<main>{children}</main>
</>
);
};
export default Layout;