React и композиция функций
При создании приложения на React бывает необходимо делать сразу несколько вещей на каждой странице:
- проверять статус аутентификации пользователя;
- проверять фича-тоглы для отображения фич;
- логирование работы компонента;
- рендер лэйаута (навигация, боковое меню и т.д.)
Подобные вещи называют сквозными проблемами. Если страниц много, то на каждую страницу приходится копировать одинаковый код для решения подобных сквозных проблем.
Чтобы избавиться от дублирования кода, можно реализовать проверки и рендер в отдельных компонентах и вложить их в друг друга:
const MyPage = ({ user = {}, signIn, features = [], log }) => {
return (
<>
<AuthStatusProvider>
<FeatureProvider>
<LogProvider>
<StandardLayout>
<div className="content">{/* our actual page content... */}</div>
</StandardLayout>
</LogProvider>
</FeatureProvider>
</AuthStatusProvider>
</>
);
};
Недостаток такого подхода в том, что если изменится список сквозных проблем, то нужно обновить код всех страниц, где используются данные вложенные компоненты.
Более оптимальный вариант решения проблемы – использовать HOC. Это функция, которая принимает компонент и возвращает новый компонент. Новый компонент рендерит оригинальный компонент, но с дополнительной логикой.
Для каждой сквозной проблемы можно создать отдельный HOC и, используя функциональную композицию, объединить их все в один HOC:
const compose = (...fns) => (x) => fns.reduceRight((y, f) => f(y), x);
const withProviders = compose(
withUser,
withFeatures,
withLogger,
withLayout
);
export default withProviders;
Теперь решения сквозных проблем собраны и изменяются в одном месте. Для использования в компоненте нужно импортировать HOC withProviders:
const MyPage = ({ user = {}, signIn, features = [], log }) => {
return <>{/* our actual page content... */}</>;
};
const MyPageWithProviders = withProviders(MyPage);
medium.com/javascr…1d4db3b1