Render props паттерн

Render Props — это подход в React, который позволяет компоненту делегировать рендеринг части интерфейса через функцию, переданную в качестве пропса. В контексте React Router render props широко используется для динамического отображения контента в зависимости от текущего маршрута и состояния навигации.

Использование render props с <Route>

Компонент <Route> из React Router поддерживает несколько способов рендеринга:

  1. Компонент через component:

    <Route path="/about" component={About} />

    Этот подход ограничен: компонент создается автоматически, и нельзя передавать дополнительные пропсы.

  2. Функция через render (Render Props):

    <Route path="/about" render={(props) => <About {...props} extraProp="value" />} />

    Здесь props включают history, location, match. Render props дают полную гибкость: можно вычислять данные, добавлять условия отображения или передавать дополнительные свойства.

Ключевой момент: render props вызываются каждый раз при изменении маршрута, что позволяет динамически реагировать на навигацию.

Пример динамической логики через render props

<Route
  path="/dashboard"
  render={({ match, location, history }) => {
    const isAdmin = checkAdminUser();
    return isAdmin ? (
      <Dashboard match={match} location={location} history={history} />
    ) : (
      <Redirect to="/login" />
    );
  }}
/>

Здесь render props позволяют встроить проверку доступа прямо в маршрутизацию, без создания отдельного компонента-обертки.

Отличие от children и component

  • component: рендерит компонент без возможности добавления логики.
  • render: передает функцию для рендеринга с доступом к маршрутизатору и позволяет внедрять кастомную логику.
  • children: вызывается всегда, даже если путь не совпадает, что полезно для компонентов, которые должны присутствовать на всех страницах (например, меню или уведомления).

Использование render props с <Switch>

В связке с <Switch> render props позволяют контролировать, какой компонент отображать на основе маршрута:

<Switch>
  <Route
    path="/profile"
    render={(props) => <Profile {...props} editable={true} />}
  />
  <Route
    path="/settings"
    render={(props) => <Settings {...props} mode="advanced" />}
  />
</Switch>

Это особенно полезно при необходимости динамически настраивать компоненты без дублирования <Route>.

Комбинирование с функциональными компонентами

Render props можно использовать внутри функциональных компонентов для создания переиспользуемых маршрутизируемых элементов:

function ProtectedRoute({ component: Component, ...rest }) {
  return (
    <Route
      {...rest}
      render={(props) =>
        isAuthenticated() ? <Component {...props} /> : <Redirect to="/login" />
      }
    />
  );
}

Такой подход позволяет создавать обертки для маршрутов с условной логикой, делая код маршрутизации чистым и понятным.

Передача дополнительных данных через render props

Render props предоставляют возможность внедрять данные в компонент маршрута без глобального состояния или контекста:

<Route
  path="/products/:id"
  render={({ match }) => {
    const product = getProductById(match.params.id);
    return <ProductDetail product={product} />;
  }}
/>

Доступ к параметрам маршрута (match.params) позволяет динамически подгружать данные и рендерить компоненты в зависимости от URL.

Практическая польза render props

  • Позволяет избегать дублирования <Route> с похожей логикой.
  • Обеспечивает доступ к навигационным объектам (history, location, match) для кастомной логики.
  • Упрощает создание защищенных маршрутов, редиректов и условного рендеринга.
  • Делает код компонентов маршрутов более гибким и переиспользуемым.

Рекомендации по применению

  • Использовать render props, когда нужен доступ к объектам маршрутизатора и возможность вставлять логику прямо в рендер.
  • Для простого рендеринга без дополнительных пропсов достаточно component.
  • Для компонентов, которые должны рендериться независимо от совпадения пути, лучше использовать children.

Render props в React Router — это мощный инструмент для построения динамических и условных маршрутов, позволяющий контролировать навигацию на уровне каждого отдельного компонента и интегрировать сложную бизнес-логику прямо в рендеринг маршрутов.