🧱 Суть

В React есть разные типы для описания JSX.

Самые распространённые:

  • React.ReactElement
  • React.ReactNode

Главное различие: ReactNode описывает всё, что React умеет отрисовывать, а ReactElementтолько JSX-элемент.

📦 Проблема

Представим тип:

type Item = {
  label: React.ReactElement;
};

Теперь:

const item: Item = {
  label: 'Личные данные',
};

TypeScript выдаст ошибку.

Причина:

string ≠ ReactElement

✅ Решение

Использовать:

type Item = {
  label: React.ReactNode;
};

Теперь можно передавать любые допустимые значения.

💻 Код

Строка:

label: 'Личные данные'

JSX:

label: <span>Тема: тёмная</span>

Фрагмент:

label: <>
  текст
  <b>и</b>
  иконка
</>

Все эти варианты имеют тип:

React.ReactNode

Что входит в каждый тип

React.ReactElement – один JSX-элемент
React.ReactNode – всё, что React может отрисовать

ReactElement

Подходит только для JSX:

const element: React.ReactElement =
  <span>Hello</span>;

Но не подходит для:

const element: React.ReactElement =
  'Hello';

ReactNode

Включает:

'строка'
123
<span>Hello</span>
<>
  Hello
  <b>World</b>
</>
null
undefined
false

и даже массивы:

[
  <Item />,
  <Item />
]

Потому что всё это React умеет рендерить.

Когда использовать

Используй ReactNode, если проп может содержать:

  • текст
  • JSX
  • фрагменты
  • условный рендер (null)
  • несколько элементов

Например:

type CardProps = {
  title: React.ReactNode;
}

Используй ReactElement, если нужен именно JSX-элемент.

Например:

type ModalProps = {
  trigger: React.ReactElement;
}

Тогда можно передать:

<Button />

Но нельзя:

'Открыть'

🎯 Вывод

  • React.ReactElement описывает только JSX-элемент
  • React.ReactNode описывает всё, что React умеет отрисовывать
  • для большинства пропсов (children, label, title, icon) обычно используют ReactNode
  • ReactElement нужен, когда требуется именно компонент или JSX-элемент

🔗 Связано