Как написать более удобочитаемые стилизованные компоненты с функциями более высокого порядка.

Если вы когда-либо использовали styled-components, вы, скорее всего, часто использовали вызовы функций для доступа к своим props следующим образом:

const StyledLink = styled.a`
  color: ${props => props.color};
`;

Использовать props для определения поведения стиля - это здорово! Это кажется более естественным и наглядным, чем объединение нескольких классов CSS друг с другом. Кроме того, в сочетании с TypeScript вы можете добавить возможность обнаружения параметров стиля для ваших компонентов. Но есть случай, когда использование функций для интерполяции вашего CSS может стать действительно беспорядочным и нечитаемым: тематика.

Возьмем, к примеру, объект темы material-ui. Доступ к значениям более сложного объекта темы может привести к следующему:

const MyBox = styled.div`
  background-color: ${props => props.theme.palette.primaryColor.main};
  color: ${props => props.theme.palette.primaryColor.contrastText};
  padding: ${props => props.theme.spacing(2)}
`;

С трудом читаете это? Я тоже! Кроме того, когда дело доходит до сканирования кода, это блокировщик, так как вам нужно останавливаться каждый раз, чтобы выяснить, к какому значению здесь на самом деле осуществляется доступ.

Здесь есть несколько проблем:

  • При чтении функций вы ожидаете, что они будут потенциально более сложными, чем просто доступ к значениям.
  • Доступ к глубоко вложенным объектам приводит к появлению длинных строк и стен текста.
  • При просмотре ключевого слова props вы думаете об использовании свойств компонентов, а не о доступе к контексту темы.
  • Стрелочные функции могут добавить много визуального беспорядка.

Многие из этих проблем можно решить с помощью функций высшего порядка.

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

Давайте посмотрим, как может выглядеть приведенный выше пример с использованием функций высшего порядка.

const MyBox = styled.div`
  background-color: ${color('primary')};
  color: ${color('primary', 'contrastText')};
  padding: ${spacing(2)}
`;

Легче читать и сканировать, не так ли?

Давайте реализуем функцию c olor:

const color = (variant, type = 'main') => 
  props => props.theme.palette[variant][type];

Кроме того, вы можете создать такие функции быстрого доступа:

const primaryColor = type => color('primary', type);
const secondaryColor = type => color('secondary', type);
const contrastTextColor = (variant) => color(variant, 'contrastText');

Но вам не нужно останавливаться на достигнутом, вы даже можете создать что-то вроде styled-system внутри более сложных стилизованных компонентов. Это очень удобно, если вы хотите объединить более 4 или 5 различных параметров стиля (в противном случае ваш JSX стал бы менее читабельным при использовании styled-system).

const MyBox = styled.div`
  ${mx(2)};
  ${mt(1)};
  ${mb(3)};
  ${shadow(2)};
  display: flex;
  justify-content: space-between;
`;

Преимущество использования чего-то подобного в том, что вы можете комбинировать более сложные стили вместе с такими значениями системы дизайна, как интервалы, тени или цвета. Написание этого в такой системе, как styled-system или @ material-ui / system, добавляет много шума в ваш настоящий JSX.

<Box mx={2} mt={1} mb={3} shadow={2} display="flex" justifyContent="space-between">
  // ...
</Box>

Также это сокращает время написания общих имен свойств css в сотни раз.

Функции полей, реализованные в теме material-ui, могут выглядеть примерно так:

Заключение

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

Каков ваш опыт работы с функциями высшего порядка в сочетании с styled-components? у вас есть вопросы? Или у вас есть еще несколько удобных вариантов использования для этого? Поделитесь со мной своими мыслями, мне интересно!

P.S .: В настоящее время мы создаем сервис для просмотра визуальных компонентов в запросах на извлечение GitHub. Таким образом, вы можете быстро показать новые и измененные компоненты дизайнерам, чтобы они могли дать обратную связь даже до того, как ваш запрос на слияние будет объединен. Если вам интересно, посетите наш сайт www.bojagi.io. Вы можете добавить себя в список ожидания бета-тестирования и сразу же приступить к работе.