Стилизация компонентов приложения React с помощью Fela

Стили в React бывают всех видов, форм и размеров. По умолчанию вы можете присваивать классы через свойство className. Также можно присваивать свойства CSS, передавая объект свойству style. В большинстве сценариев этих методов более чем достаточно, однако они, конечно, не лишены недостатков. К примеру, чтобы сделать classNames динамическим, необходимо определить дополнительные классы и свойства style; а чтобы разрешить использование динамических свойств, требуется шаблонный код, который не дает углубиться в свойства псевдоклассов типа :hover. Как раз для таких ситуаций и придумали Fela.

Fela – это не зависящая от фреймворка библиотека JavaScript для обработки стилей на основе состояния. Она очень мощная и довольно гибкая. Fela можно использовать отдельно, а можно вместе с react-fela – библиотекой привязок React для ваших приложений React.js.

Начало работы с Fela

Для начала нужно добавить react-fela в свой проект. Это можно сделать через npm:

$ npm install --save react-fela

Или через Yarn:

$ yarn add react-fela

В этом руководстве мы будем использовать некоторые методы прямо из библиотеки fela. Но не волнуйтесь, react-fela включает эту зависимость, так что все будет в порядке, если вы захотите добавить ее.

Что такое createRenderer

Часть библиотеки fela, которую мы будем использовать здесь, называется createRenderer. Метод createRenderer используется для создания средства визуализации, которому будет передан компонент Provider – он, в свою очередь, создаст оболочку для всех компонентов, использующих Fela.

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

Использование сгенерированных CSS-классов

Ниже вы найдете не самый сложный пример Fela: он не идеален, но в нем меньше всего шаблонного кода.

Основной принцип работы Fela заключается в том, что он принимает предоставленные стили, генерирует соответствующий CSS с атомарными классами и позволяет извлечь полученные CSS-классы, которые можно передать в свойство classNames любого компонента:

import React from "react";

import { render } from "react-dom";

import { createRenderer } from "fela";

import { Provider } from "react-fela";

const renderer = createRenderer();

const rule = ({

  backgroundColor = "#6db65b",

  borderColor = "#efbb35",

  padding

}) => ({

  backgroundColor: backgroundColor,

  border: `10px solid ${borderColor}`,

  color: "#fff",

  fontWeight: "bold",

  padding: `${padding}px`,

  ":hover": {

    cursor: "pointer",

    filter: "drop-shadow(0 10px 19px rgba(0, 0, 0, 0.3))"

  }

});

const container = document.createElement("div");

document.body.appendChild(container);

render(

  <Provider renderer={renderer}>

    <div className={renderer.renderRule(rule, { padding: 100 })}>

      Hover Over Me!

    </div>

  </Provider>,

  container

);

Как вы можете видеть в этом примере, renderer используется для генерации CSS и имен классов на основе объекта передаваемых CSS-свойств.

rule – это простая анонимная функция, которая возвращает объект со всеми переданными свойствами.

Поскольку rule – это просто функция с возвращаемым объектом, вместо немедленного возврата ожидаемого объекта вы можете по своему усмотрению включить дополнительную логику.

Использование компонентных примитивов

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

В подобных сценариях мы могли бы использовать примитив FelaComponent для создания нового компонента:

import React from "react";

import { render } from "react-dom";

import { createRenderer } from "fela";

import { FelaComponent, Provider } from "react-fela";

const renderer = createRenderer();

const rule = ({

  backgroundColor = "#6db65b",

  borderColor = "#efbb35",

  padding

}) => ({

  backgroundColor: backgroundColor,

  border: `10px solid ${borderColor}`,

  color: "#fff",

  fontWeight: "bold",

  padding: `${padding}px`,

  ":hover": {

    cursor: "pointer",

    filter: "drop-shadow(0 10px 19px rgba(0, 0, 0, 0.3))"

  }

});

const PaddedContainer = ({

  backgroundColor,

  borderColor,

  padding,

  children

}) => (

  <FelaComponent

    rule={rule}

    backgroundColor={backgroundColor}

    borderColor={borderColor}

    padding={padding}

  >

    {children}

  </FelaComponent>

);

const container = document.createElement("div");

document.body.appendChild(container);

render(

  <Provider renderer={renderer}>

    <PaddedContainer padding={100}>

      Hover Over Me!

    </PaddedContainer>

  </Provider>,

  container

);

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

Самостоятельное создание компонентов

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

import React from "react";

import { render } from "react-dom";

import { createRenderer } from "fela";

import { createComponent, Provider } from "react-fela";

const renderer = createRenderer();

const rule = ({

  backgroundColor,

  borderColor,

  padding

}) => ({

  backgroundColor: backgroundColor,

  border: `10px solid ${borderColor}`,

  color: "#fff",

  fontWeight: "bold",

  padding: `${padding}px`,

  ":hover": {

    cursor: "pointer",

    filter: "drop-shadow(0 10px 19px rgba(0, 0, 0, 0.3))"

  }

});

const AnotherPaddedContainer = createComponent(rule);

const container = document.createElement("div");

document.body.appendChild(container);

render(

  <Provider renderer={renderer}>

    <AnotherPaddedContainer padding={100}>Hover Over Me!</AnotherPaddedContainer>

  </Provider>,

  container

);

Получается немного чище. Такой код можно использовать повторно (точно так же, как пример с компонентными примитивами).

Заключение  

Независимо от того, какой подход вы выберете, вы по-прежнему можете сократить время, необходимое для динамической стилизации компонентов в React – для этого обратитесь к react-fela. Эта библиотека сокращает количество шаблонов, которые нужно написать.

Увидеть приведенные выше примеры кода в действии можно в этой песочнице CodeSandbox.

Читайте также: Промисы в JavaScript ES6/ES2015

Tags: , , ,

Добавить комментарий