reactjs - Eroare TypeScript: Proprietatea 'children' nu există pe tipul 'ReactNode'
export const PageViewTracker = ({ children }: ReactNode): ReactElement => {
usePageView();
return children;
};
Problemă:
Această funcție returnează eroarea »Proprietatea 'children' nu există pe tipul 'ReactNode'«
Abordarea mea pentru soluție:
Am încercat mai multe tipuri, dar doar any funcționează, ceea ce nu este ceea ce vreau. De obicei foloseam ReactNode pentru props-urile children și funcționa bine. În acest caz, se pare că TypeScript are probleme.
Răspuns #1
React >=18
În React 18, interfața FunctionalComponent s-a schimbat pentru a deveni:
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;
}
Rețineți că tipul PropsWithChildren este omis din tipul props al unui FunctionalComponent după React 18, ceea ce înseamnă că trebuie să includeți singur proprietatea children:
interface Props {
children: React.ReactNode;
}
export const PageViewTracker: React.FC<Props> = ({ children }) => {
}
Motivul pentru care au eliminat proprietatea implicită children poate fi găsit aici. (sursa notelor de lansare pentru definiția de tipuri din React 18).
Tipul PropsWithChildren este încă disponibil în tipările React, așa că dacă vrei în continuare să ai opțional children ca props, la fel ca versiunile anterioare React 18, poți să faci în continuare:
import { PropsWithChildren } from 'react';
interface Props {
foo: string;
}
export const PageViewTracker: React.FC<PropsWithChildren<Props>> = ({ children, foo }) => {
}
Definiția tipului pentru PropsWithChildren este:
type PropsWithChildren<P = unknown> = P & { children?: ReactNode | undefined };
React <=17
Motivul pentru care primești acea eroare este că oferi interfața 'ReactNode' unui obiect ({}: Type). children în sine este de tipul ReactNode:
type PropsWithChildren<P> = P & { children?: ReactNode };Ar trebui să dai tracker-ului tău PageView tipul FunctionComponent (sau aliasul său FC).
export const PageViewTracker: React.FC = ({ children }) => {
...
}
care are următoarea interfață:
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement | null;
propTypes?: WeakValidationMap<P>;
contextTypes?: ValidationMap<any>;
defaultProps?: Partial<P>;
displayName?: string;
}
Deci, în mod implicit, acceptă proprietatea children, care are tipul 'ReactNode'.
Răspunsul #2
Notă importantă: după React 18.0.0, te obligă să incluzi children în fiecare interfață FC.
interface MyButtonProps {
color: string;
children?: React.ReactNode;
}
Apoi poți să treci proprietăți ca în versiunile mai vechi.
const Button:React.FC<MyButtonProps> = (props) => {
//use children with {props.children} just like before
}
Din documente
Răspunsul #3
Pentru „@types/react”: „17.0.43”, sau mai puțin de 18
import { FunctionComponent } from "react";
const BaseLayout: FunctionComponent = ({ children }) => {
return (
<>
</>
);
};
export default BaseLayout;
Pentru „@types/react” > 18
interface BaseLayoutProps {
children?: ReactNode;
}
const BaseLayout: FunctionComponent<BaseLayoutProps> = ({ children }) => {
return (
<>
</>
);
};
Dar pentru unele cazuri, încă trebuie să folosești FunctionComponent. De exemplu:
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>
);
}
Dacă transmiți ReactNode, primești eroarea „tipul ReactNode nu poate fi apelat”
