JavaRush /Курсы /Модуль 3: React /Что такое рендер-пропсы и их назначение

Что такое рендер-пропсы и их назначение

Модуль 3: React
4 уровень , 5 лекция
Открыта

Понятие рендер-пропсов

Как и компоненты высшего порядка, рендер-пропсы (англ. render props) — это шаблон проектирования в React, предназначенный для переиспользования логики между компонентами. Основная идея заключается в том, что компонент получает функцию в качестве пропса, а затем использует её для управления рендерингом.

Если это звучит немного запутанно, вот простая аналогия: представьте пиццерию. Пиццерия предоставляет вам печь (компонент), но какие ингредиенты вы добавите на тесто (какая функция будет передана) — зависит только от вас. В итоге, результат зависит от вашей фантазии!

Как это выглядит в коде:

type RenderPropsExampleProps = {
  render: (name: string) => JSX.Element;
};

const RenderPropsExample: React.FC<RenderPropsExampleProps> = ({ render }) => {
  const name = "React Developer";
  return <divм{render(name)}</div>;
};

// Использование
<RenderPropsExample
        render={(name) => <h1>Hello, {name}!</h1>}
/>;

В данном случае RenderPropsExample передаёт имя name через функцию render. Вызов функции инициализируется внутри компонента, а результат отображается на странице. Фантазируйте — вы можете рендерить что угодно, даже немытые чашки (но лучше не надо).

Зачем использовать рендер-пропсы?

С того самого момента, как вы начали писать компоненты React, скорее всего, вы сталкивались с задачами, где нужна гибкость. Простая передача данных через пропсы решает определённый круг проблем, но если дело касается переиспользования сложной логики, то рендер-пропсы начинают блистать.

Преимущества рендер-пропсов

  • Функциональная гибкость: вы можете делегировать контроль над тем, что именно будет рендериться компонентом, предоставляя свою собственную функцию.
  • Переиспользуемость логики: можно изолировать бизнес-логику в компоненте, а UI передать на откуп дочерним компонентам.
  • Свобода в рендеринге: можно показывать совершенно разные интерфейсы на базе одной логики.

Как это работает? Основы рендер-пропсов

Представим, что мы делаем компонент, который следит за координатами мыши на экране. Используя рендер-пропсы, это будет выглядеть так:

Пример "Отслеживание мыши"

// Компонент, использующий рендер-пропсы
type MouseTrackerProps = {
  render: (state: { x: number; y: number }) => JSX.Element;
};

const MouseTracker: React.FC<MouseTrackerProps> = ({ render }) => {
  const [position, setPosition] = React.useState({ x: 0, y: 0 });

  const handleMouseMove = (event: React.MouseEvent) => {
    setPosition({ x: event.clientX, y: event.clientY });
  };

  return (
    <div style={{ height: "100vh" }} onMouseMove={handleMouseMove}>
      {render(position)}
    </div>
  );
};

// Использование MouseTracker
const App = () => (
  <MouseTracker
    render={({ x, y }) => (
      <h1>
        Твоя мышка находится по координатам ({x}, {y})!
      </h1>
    )}
  />
);

Что здесь происходит?

  1. MouseTracker — это компонент, который отслеживает координаты мыши.
  2. В него передаётся функция render, которая получает текущие координаты мышки x и y и возвращает разметку, что нужно отобразить.
  3. Логику отслеживания координат обрабатывает MouseTracker, а что отображать — решает переданная функция.

Именно это делает рендер-пропсы такими мощными: вы отделяете логику поведения от логики рендеринга.

Гибкость использования рендер-пропсов

Рендер-пропсы — это не обязательно замена компонентов высшего порядка, скорее это дополнительный инструмент. Вот пример ещё одной задачи: представьте, что вам нужно показать индикатор в процессе загрузки данных. Легко!

type LoaderProps = {
  isLoading: boolean;
  render: (isLoading: boolean) => JSX.Element;
};

const Loader: React.FC<LoaderProps> = ({ isLoading, render }) => {
  return (
    <div>
      {isLoading ? <p>Загрузка...</p> : render(isLoading)}
    </div>
  );
};

// Использование Loader
const App = () => (
  <Loader
          isLoading={true}
          render={() => (
      <h1>Загрузка завершена. Вот ваши данные!</h1>
    )}
  />
);

Если вы видите компонент, который занимается "логикой поведения" (например, Loader), то рендер-пропсы помогут сделать его максимально абстрактным и переиспользуемым.

Типизация функций рендер-пропсов

Рендер-пропсы — это в первую очередь функции, поэтому для их типизации мы будем использовать типы и интерфейсы. Рассмотрим, как это сделать.

type MouseTrackerProps = {
  render: (state: { x: number; y: number }) =< JSX.Element;
};

// Всё работает как и ожидалось!
const App = () =< (
  <MouseTracker
          render={({ x, y }) =< <div>Mouse is at ({x}, {y})</div<}
  />
);

Здесь render строго типизирован как функция, принимающая объект с координатами x и y и возвращающая JSX.Element. Если вы попытаетесь передать в неё что-то не то (например, забыли параметры), TypeScript всё мгновенно обнаружит и подскажет.

Когда использовать рендер-пропсы, а когда HOC?

Битва старой школы (HOC) и рендер-пропсов всегда актуальна. Выбирая между ними, нужно учитывать конкретные задачи вашего проекта.

  • HOC лучше подходит для случаев, когда нужно обернуть несколько компонентов одинаковой логикой.
  • Рендер-пропсы более уместны, когда требуется гибкость и контроль над рендерингом на уровне вызова.

В реальном проекте вы можете использовать оба подхода. Более того, рендер-пропсы проще интегрировать в уже существующий проект, если он не планировался с учётом HOC.

Типичные ошибки и особенности

Использование рендер-пропсов открывает массу возможностей, но есть и подводные камни. Например, если вы передаёте слишком много данных в render, логика может стать сложно читаемой. Чтобы избежать громоздкости, старайтесь делить крупные компоненты на более мелкие и следите за чистотой функций.

Также будьте аккуратны с производительностью: из-за частых перерисовок компонентов могут возникать лишние рендеры. Если это произойдёт, вспомните про React.memo и используйте его для контроля.

1
Задача
Модуль 3: React, 4 уровень, 5 лекция
Недоступна
Отображение текущего времени
Отображение текущего времени
1
Задача
Модуль 3: React, 4 уровень, 5 лекция
Недоступна
Отслеживание положения мыши
Отслеживание положения мыши
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ