У меня есть очень простой функциональный компонент:
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]
Как мне это правильно набрать?
JSX.Element
недостаточно хорош, так как допустимые дочерние элементы React могут быть строкой, логическим значением, нулем ...ReactChild
тоже неполны по тем же причинамReactNode
. Это не помогает с точки зрения безопасности типов, подобно тому,children
как печатать какany
- см. Мой ответ для объяснения.Чтобы использовать
<Aux>
в JSX, это должна быть функция, которая возвращаетReactElement<any> | null
. Это определение функционального компонента .Однако в настоящее время он определяется как функция, которая возвращает
React.ReactNode
, что является гораздо более широким типом. Как говорится в типизации React:Убедитесь, что нежелательные типы нейтрализованы, заключив возвращаемое значение в React Fragment (
<></>
):источник
children
фрагмент React. Не хочешь объяснить? В React вполне допустимо простоreturn children;
.children
это массив. В этом случае вам нужно либо обернуть их в один узел, либо использовать фрагменты React.return React.Children.count(children) > 1 ? <>{children}</> : children
но машинопись на это жалуется. Я заменил его на просто<>{children}</>
.children
это список элементов, который содержит только 1 элемент. Думаю, сработало бы, если бы вы сделалиreturn React.Children.count(children) > 1 ? <>{children}</> : children[0]
@sanfilippopablo<React.Fragment>
окружением{props.children}
я ничего не возвращаю.Вот что сработало для меня:
Изменить Я бы рекомендовал использовать
children: React.ReactNode
вместо этого сейчас.источник
<MyComponent>{ condition ? <span>test</span> : null}</MyComponent>
. Использованиеchildren: ReactNode
будет работать.вы можете объявить свой компонент следующим образом:
источник
Вы можете использовать
ReactChildren
иReactChild
:источник
С сайта TypeScript: https://github.com/Microsoft/TypeScript/issues/6471
Это сработало для меня. Дочерним узлом может быть много разных вещей, поэтому явная типизация может пропустить случаи.
Здесь более подробно обсуждается следующая проблема: https://github.com/Microsoft/TypeScript/issues/13618 , но любой подход все еще работает.
источник
Тип возвращаемого значения функционального компонента ограничен
JSXElement | null
в TypeScript. Это текущее ограничение типа, чистый React допускает больше типов возвращаемых значений.Минимальный демонстрационный фрагмент
В качестве временного решения можно использовать утверждение типа или фрагменты:
ReactNode
children: React.ReactNode
может быть неоптимальным, если цель состоит в том, чтобы иметь сильные типы дляAux
.Текущему
ReactNode
типу можно присвоить почти все , что эквивалентно{} | undefined | null
. Более безопасным вариантом для вашего случая может быть:Пример:
Учитывая
Aux
потребности в элементах React aschildren
, мы случайно добавилиstring
к нему. Тогда приведенное выше решение будет ошибкой, в отличие отReactNode
- взгляните на связанные игровые площадки.Типизированные
children
также полезны для свойств, отличных от JSX, например для обратного вызова Render Prop .источник
Вы также можете использовать
React.PropsWithChildren<P>
.источник
Общий способ найти любой тип на примере. Прелесть машинописного текста в том, что у вас есть доступ ко всем типам, если у вас есть правильные
@types/
файлы.Чтобы ответить на этот вопрос, я просто подумал о том, что компонент React использует эту
children
опору. Первое, что пришло в голову? А как насчет<div />
?Все, что вам нужно сделать, это открыть vscode и создать новый
.tsx
файл в проекте реакции с помощью@types/react
.При наведении курсора на
children
опору отображается тип. А что вы знаете - его типReactNode
(не нуженReactNode[]
).Затем, если вы щелкните определение типа, вы сразу перейдете к определению
children
исходящего изDOMAttributes
интерфейса.источник
В качестве типа, содержащего детей, я использую:
Этот тип дочернего контейнера достаточно универсален, чтобы поддерживать все различные случаи, а также согласован с API ReactJS.
Итак, для вашего примера это будет примерно так:
источник
Эти ответы кажутся устаревшими - React теперь имеет встроенный тип
PropsWithChildren<{}>
. Он определяется аналогично некоторым правильным ответам на этой странице:type PropsWithChildren<P> = P & { children?: ReactNode };
источник
P
в случае с этим типом?P
тип реквизита вашего компонентаУ меня всегда работало:
источник
Компоненты React должны иметь один узел-оболочку или возвращать массив узлов.
У вашего
<Aux>...</Aux>
компонента есть два узлаdiv
иmain
.Попробуйте заключить своих детей
div
вAux
компонент in .источник