Pull to refresh

Разбираемся с Render Props на примере

Reading time 3 min
Views 25K
Привет, Хабр! Представляю вашему вниманию перевод статьи «Learn Render Props by Example».

image

Честно говоря, раньше я не представлял ситуаций, в которых можно применить React render props, пока не увидел практический пример, поэтому, поехали! Или можете прочитать TLDR;

Ситуация:

Нам поручено создать кнопку, открывающую окно PayPal:
image

Мы открываем наш редактор и создаем компонент PayPalLauncher:

image

PayPalLauncher может содержать экземпляр PayPal, с дополнительной логикой, поэтому неплохо было бы обернуть его (PayPal) в компонент.

Но что, если требуется использовать дополнительные элементы PayPal? Например:

image

Теперь у нас есть две кнопки и оранжевая ссылка, которая должна открыть окно PayPal. Давайте рассмотрим несколько способов реализовать это.

Вариант 1 – Логика в render()

Вначале у вас может возникнуть соблазн написать код внутри PayPalLauncher:

image

Здесь мы передаем prop, называемый type для того, чтобы определить какой элемент PayPal рендерить. Много логики, чтобы выразить несколько визуальных изменений. Это все еще не дает нам возможности легко отрисовывать любой компонент по необходимости. Что если есть способ отделить логику от представления?

Вариант 2 — Вложенность

Вложенность помогает нам писать более понятный JSX.

image

Теперь у нас есть четкое разделение между логикой (PayPalLauncher) и представлением (PayPalButton). Это дает нам возможность отображать любой компонент в качестве элемента PayPal (PayPal trigger). И это хорошо читается! Но как мы передаем props между PayPalLauncher и PayPalButton? Давайте посмотрим как это выглядит в PayPalLauncher:

image

Что здесь происходит?! Мы клонируем children и предаем prop в launchPayPal неявно, каждому ребенку. Это значит, что каждый ребенок, которого вы вложите в PayPalLauncher, должен принимать prop launchPayPal. Хотя вложенность дает нам более понятный JSX, этот метод не является идеальным, особенно если мы пытаемся создать переиспользуемые компоненты с общими интерфейсами.

Вариант 3 — Render Props

Render Props — это метод передачи props от родителя ребенку, используя функцию или замыкание. Давайте посмотрим, как это выглядит:

image

Вместо того, чтобы обрабатывать props.children в качестве ноды, мы создаем замыкание и выбираем аргументы для передачи дочерним нодам. В этом случае мы используем метод экземпляра класса launchPayPal.

Когда мы реализуем это, полученный вариант будет выглядеть так:

image

Что это значит? Вместо элементов, мы передаем функцию как ребенка в PayPalLauncher. Из-за этого мы можем легко передать launchPayPal в обработчик onClick компонента PayPalButton. Теперь мы можем рендерить любой нужный нам компонент, и мапить родительский launchPayPal в любой обработчик ребенка.

Немного больше:

Неожиданным преимуществом использования render props является то, что этот подход дает возможность передавать launchPayPal в Page, и позволяет нам добавлять больше функциональности. Например, допустим, вы хотите зарегистрировать пользователя и подтвердить форму перед запуском окна PayPal:

image

Поскольку launchPayPal отображается через render props на Page, мы можем легко добавить дополнительный контекстно-зависимый функционал, используя композицию функций. Здесь мы сохраняем разницу между Page и PayPalLauncher и используем pipe, чтобы улучшить читаемость.

Резюме

Что мы получаем при использовании render props?

  • Переиспользование логики — отделяя отображение от логики, нам не нужно подгонять логику под каждый компонент или визуальное представление.
  • Чистый и хорошо читаемый JSX.
  • Улучшается структура и функциональная составляющая наших React приложений.

Вы тоже беспокоитесь о работе ваших React приложений? Открыты вакансии!

* Помните, что render props является паттерном и может быть реализован несколькими способами — только вы должны выбирать, что использовать с вашем случае.
Tags:
Hubs:
+12
Comments 3
Comments Comments 3

Articles