← Назад к вопросам

Как работает Props.children?

2.0 Middle🔥 251 комментариев
#React

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Концепция children в React

Props.children — это специальный prop в React, который позволяет компонентам принимать вложенный контент. Это один из самых мощных паттернов для создания переиспользуемых и гибких компонентов.

Что такое children?

Children — это реактовский prop, который содержит все элементы, переданные между открывающим и закрывающим тегом компонента.

// Пример использования
<MyComponent>
  <p>Это children</p>
  <span>Это тоже children</span>
</MyComponent>

// В компоненте:
function MyComponent(props) {
  console.log(props.children); // Вернет массив: [<p>, <span>]
}

Синтаксис с деструктуризацией

// Способ 1: Деструктуризация в параметрах функции
function Card({ children }) {
  return (
    <div className="card p-4 border rounded">
      {children}
    </div>
  );
}

// Способ 2: Деструктуризация внутри функции
function Button(props) {
  const { children, onClick } = props;
  return (
    <button onClick={onClick}>
      {children}
    </button>
  );
}

// Способ 3: Использование всех props включая children
function Layout({ children, ...otherProps }) {
  return (
    <main {...otherProps}>
      {children}
    </main>
  );
}

Практические примеры

// Пример 1: Обертка компонента (Wrapper)
export function Container({ children }) {
  return (
    <div className="max-w-7xl mx-auto px-4">
      {children}
    </div>
  );
}

// Использование:
<Container>
  <h1>Hello World</h1>
  <p>Welcome</p>
</Container>

// Пример 2: Модальное окно с children
export function Modal({ children, isOpen, onClose }) {
  if (!isOpen) return null;

  return (
    <div className="fixed inset-0 bg-black/50 flex items-center justify-center">
      <div className="bg-white p-8 rounded-lg">
        <button onClick={onClose} className="float-right">x</button>
        {children}
      </div>
    </div>
  );
}

// Использование:
<Modal isOpen={showModal} onClose={handleClose}>
  <h2>Modal Title</h2>
  <p>Modal content goes here</p>
</Modal>

// Пример 3: Conditional rendering с children
export function TabPanel({ children, isActive }) {
  return isActive ? <div>{children}</div> : null;
}

// Пример 4: Multiplication с children (render props pattern)
export function DataProvider({ children, data, loading }) {
  return (
    <>
      {loading && <p>Loading...</p>}
      {!loading && children}
    </>
  );
}

// Использование:
<DataProvider data={users} loading={isLoading}>
  <UserList users={users} />
</DataProvider>

React.Children API

React предоставляет утилиты для работы с children:

import { Children, cloneElement } from 'react';

// Пример 1: Подсчет children
export function Tabs({ children }) {
  const count = Children.count(children);
  return (
    <div>
      <p>Количество табов: {count}</p>
      {children}
    </div>
  );
}

// Пример 2: Итерация по children
export function ButtonGroup({ children }) {
  return (
    <div className="flex gap-2">
      {Children.map(children, (child, index) => (
        <div key={index} className="flex-1">
          {child}
        </div>
      ))}
    </div>
  );
}

// Пример 3: Добавление props ко всем children
export function FormGroup({ children }) {
  return (
    <div className="space-y-4">
      {Children.map(children, (child) => {
        if (!child) return null;
        return cloneElement(child, {
          className: `${child.props.className || ''} required`,
        });
      })}
    </div>
  );
}

TypeScript типизация children

import { ReactNode, FC } from 'react';

// Способ 1: Простой тип
interface CardProps {
  children: ReactNode;
}

function Card({ children }: CardProps) {
  return <div className="card">{children}</div>;
}

// Способ 2: С использованием FC (Function Component)
const Button: FC<{ children: ReactNode }> = ({ children }) => {
  return <button>{children}</button>;
};

// Способ 3: Специфичные типы children
interface LayoutProps {
  children: ReactNode;
  header?: ReactNode;
  footer?: ReactNode;
}

export function Layout({ children, header, footer }: LayoutProps) {
  return (
    <>
      {header && <header>{header}</header>}
      <main>{children}</main>
      {footer && <footer>{footer}</footer>}
    </>
  );
}

Важные моменты

  1. Children может быть:

    • Одним элементом
    • Массивом элементов
    • Строкой
    • Числом
    • null или undefined
  2. Key prop: При использовании Children.map() обязателен key для каждого элемента

  3. Композиция: Children паттерн идеален для создания композируемых компонентов

  4. Производительность: Избегай излишней работы с children в render методе

// Плохо - пересчитываем children каждый раз
function Bad({ children }) {
  const childArray = React.Children.toArray(children);
  return <div>{childArray.length}</div>;
}

// Хорошо - кэшируем результат
function Good({ children }) {
  const childCount = React.useMemo(
    () => React.Children.count(children),
    [children]
  );
  return <div>{childCount}</div>;
}

Props.children — это фундаментальный паттерн в React, который позволяет создавать мощные, переиспользуемые и гибкие компоненты.