Какой тип имеет проп 'children'?
У меня есть очень простой функциональный компонент, который выглядит следующим образом:
import * as React from 'react';
export interface AuxProps {
children: React.ReactNode
}
const aux = (props: AuxProps) => props.children;
export default aux;
А вот и другой компонент:
import * as React from "react";
export interface LayoutProps {
children: React.ReactNode
}
const layout = (props: LayoutProps) => (
<Aux>
<div>Toolbar, SideDrawer, Backdrop</div>
<main>
{props.children}
</main>
</Aux>
);
export default layout;
Я постоянно получаю следующую ошибку:
[ts]
JSX элемент типа 'ReactNode' не является функцией-конструктором для JSX элементов.
Тип 'undefined' не может быть присвоен типу 'ElementClass'. [2605]
Как правильно задать типы в этом случае?
5 ответ(ов)
В вашем случае, чтобы указать тип для children
в компоненте React, достаточно использовать children: React.ReactNode
. Это позволяет вашему компоненту принимать любые валидные элементы React в качестве дочерних компонентов, включая строки, числа, массивы, элементы и даже фрагменты. Пример объявления пропс для компонента может выглядеть так:
import React from 'react';
interface MyComponentProps {
children: React.ReactNode;
}
const MyComponent: React.FC<MyComponentProps> = ({ children }) => {
return <div>{children}</div>;
};
Таким образом, React.ReactNode
является универсальным типом, который позволяет вам гибко использовать компонент с различными типами дочерних элементов.
Чтобы использовать <Aux>
в вашем JSX, он должен быть функцией, возвращающей ReactElement<any> | null
. Это определение функционального компонента.
Тем не менее, в данный момент он определен как функция, возвращающая React.ReactNode
, что является более широким типом. Как говорится в типах React:
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
Убедитесь, что нежелательные типы нейтрализованы, обернув возвращаемое значение в React Fragment (<></>
):
const aux: React.FC<AuxProps> = props =>
<>{props.children}</>;
Вам также можно использовать React.PropsWithChildren<P>
для определения пропсов компонента с дочерними элементами. Вот пример, как это можно сделать:
type ComponentWithChildProps = React.PropsWithChildren<{ example?: string }>;
В этом примере ComponentWithChildProps
будет содержать свойство example
, которое является опциональным, а также автоматически включает children
, что упрощает работу с дочерними элементами в вашем компоненте.
Вы можете использовать ReactChildren
и ReactChild
:
import React, { ReactChildren, ReactChild } from 'react';
interface AuxProps {
children: ReactChild | ReactChildren;
}
const Aux = ({ children }: AuxProps) => (<div>{children}</div>);
export default Aux;
Если вам нужно передавать плоские массивы элементов, вы можете изменить интерфейс следующим образом:
interface AuxProps {
children: ReactChild | ReactChild[] | ReactChildren | ReactChildren[];
}
Таким образом, ваш компонент сможет принимать как одиночные элементы, так и массивы элементов в качестве дочерних элементов.
Это сработало для меня:
interface Props {
children: JSX.Element[] | JSX.Element
}
Правка: Теперь я бы рекомендовал использовать children: React.ReactNode
.
Цикл внутри JSX в React
Когда использовать JSX.Element, ReactNode и ReactElement?
Обнаружена ошибка: Невозможное нарушение: Неверный тип элемента: ожидался строковый тип (для встроенных компонентов) или класс/функция, но получен объект
Интерфейсы vs Типы в TypeScript
Что такое "*.d.ts" в TypeScript?