В библиотеке MUI (Material-UI) Render Props представляют собой технику, позволяющую передавать компоненту функцию, которая управляет рендерингом внутренней части компонента. Эта концепция особенно полезна для компонентов, у которых есть сложная логика состояния или поведения, но требуется гибкость в том, как отображается пользовательский интерфейс.
Пример базового использования в MUI:
import React from 'react';
import { Popper, Button } from '@mui/material';
function Example() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => {
setAnchorEl(anchorEl ? null : event.currentTarget);
};
const open = Boolean(anchorEl);
return (
<div>
<Button onCl ick={handleClick}>Toggle Popper</Button>
<Popper open={open} anchorEl={anchorEl}>
{({ placement }) => (
<div style={{ padding: 10, background: 'lightgray' }}>
Popper размещен {placement}
</div>
)}
</Popper>
</div>
);
}
Здесь Popper использует render prop для
передачи объекта с информацией о размещении (placement)
внутрь функции, которая возвращает JSX. Это позволяет динамически
изменять разметку в зависимости от состояния компонента.
Пример сравнения:
// Children
<Popper open={open} anchorEl={anchorEl}>
<div>Статический контент</div>
</Popper>
// Render Prop
<Popper open={open} anchorEl={anchorEl}>
{({ placement }) => <div>Текущее размещение: {placement}</div>}
</Popper>
Render Props обеспечивают гибкость, позволяя компонентах передавать данные о состоянии, которые нельзя получить напрямую через обычные дочерние элементы.
В MUI ряд компонентов активно используют Render Props:
renderOption и
renderInput.MenuListProps можно
управлять рендерингом внутренних элементов.children как
функции можно полностью контролировать, какой элемент оборачивается
тултипом.Пример кастомизации Autocomplete:
import { Autocomplete, TextField } from '@mui/material';
const options = ['Apple', 'Banana', 'Cherry'];
function FruitSelector() {
return (
<Autocomplete
options={options}
renderInput={(params) => <TextField {...params} label="Выберите фрукт" />}
renderOption={(props, option) => (
<li {...props} style={{ color: option === 'Banana' ? 'yellow' : 'black' }}>
{option}
</li>
)}
/>
);
}
Здесь renderInput и renderOption — это
render props, позволяющие управлять разметкой поля ввода и отдельных
опций списка.
Render Props могут получать разные параметры, в зависимости от
компонента MUI. Например, в Popper это:
placement – положение относительно якоря
(top, bottom, left,
right).arrowProps – стили для стрелки, если она
используется.TransitionProps – управление анимацией появления.В Autocomplete:
props – набор атрибутов для элемента списка,
необходимых для корректного рендеринга.option – конкретная опция списка.state – текущее состояние автокомплита
(inputValue, value, focused и
др.).Пример использования параметров:
<Popper open={open} anchorEl={anchorEl}>
{({ placement, arrowProps }) => (
<div>
<div {...arrowProps} style={{ width: 10, height: 10, background: 'gray' }} />
<span>Размещено {placement}</span>
</div>
)}
</Popper>
Render Props позволяют интегрировать MUI с собственными компонентами, сохраняя управление состоянием и стилизацией.
Пример с кастомной кнопкой внутри Menu:
import { Menu, MenuItem, Button } from '@mui/material';
import React from 'react';
function CustomMenu() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => setAnchorEl(event.currentTarget);
const handleClose = () => setAnchorEl(null);
return (
<div>
<Button onCl ick={handleClick}>Открыть меню</Button>
<Menu anchorEl={anchorEl} open={Boolean(anchorEl)} onCl ose={handleClose}>
{({ onItemClick }) => (
<>
<MenuItem onCl ick={() => { onItemClick(); console.log('Первый элемент'); }}>Первый</MenuItem>
<MenuItem onCl ick={() => { onItemClick(); console.log('Второй элемент'); }}>Второй</MenuItem>
</>
)}
</Menu>
</div>
);
}
Даже если MUI не документирует onItemClick для всех
компонентов, практика render props позволяет добавить кастомные
обработчики, сохраняя согласованность с внутренним API.
useAutocomplete,
usePopper) для более сложных сценариев.Render Props в MUI — это мощный инструмент, позволяющий создавать гибкие, динамичные интерфейсы без потери контроля над состоянием и поведением компонентов. Они расширяют возможности стандартных компонентов и дают свободу интеграции с кастомной логикой и визуальными решениями.