От автора: Front end экосистема развивается чрезвычайно быстро, с ростом таких фреймворков, как React, Vue и Angular, что приводит к резким изменениям в архитектуре приложений и целым новым наборам шаблонов для разработчиков JavaScript. С WordPress, охватывающим React в новом редакторе Gutenberg, миллионы разработчиков внезапно внедряются в этот мир и пытаются не отстать от нововведений.
В этой статье мы собираемся сломать один из тех архитектурных шаблонов, который чрезвычайно распространен, когда в дело идет компонент высшего порядка React.
Недавно друг попросил объяснить суть новой утилиты, добавленной в Gutenberg для управления цветами, компонента withColors более высокого порядка. Здесь вы можете увидеть пример, воспроизведенный ниже:
edit: withColors( 'backgroundColor', { textColor: 'color' } )( function( props ) { // Props added by withColors HOC. var backgroundColor = props.backgroundColor; var setBackgroundColor = props.setBackgroundColor; var textColor = props.textColor; var setTextColor = props.setTextColor; // Class computation var paragraphClasses = ( ( backgroundColor.class || '' ) + '' + ( textColor.class || '' ) ).trim(); return el( Fragment, {}, el( 'p', { className: paragraphClasses, style: { backgroundColor: backgroundColor.value, color: textColor.value, } }, 'Hello world' ), el( InspectorControls, {}, el( PanelColor, { colorValue: backgroundColor.value, title: __( 'Background Color' ), onChange: setBackgroundColor, } ), el( PanelColor, { colorValue: textColor.value, title: __( 'Text Color' ), onChange: setTextColor, } ) ) ); } ),
Немного пугает — что конкретно здесь происходит? Функция withColors реализует шаблон, называемый компонентом более высокого порядка. Давайте разберем, что это значит:
Компоненты высокого порядка
Компонент более высокого порядка (HOC) представляет собой концепцию React, которая является композиционно-ориентированным способом инкапсуляции общей логики, поэтому вы можете использовать ее для многих компонентов.
Как определено в документации React: Компонент более высокого порядка — это функция, которая принимает компонент и возвращает новый компонент.
Это во многом аналогично декоратору, что позволяет вам инкапсулировать некоторые функции многократного использования (например, логику получения и настройки цветов) или данные в «компонентной оболочке».
Эта оболочка — это функция, которая принимает компонент и возвращает «завернутую» версию этого компонента, которая будет получать эти функции и данные в качестве props.
Поэтому вместо каждого компонента, который должен иметь доступ к информации о цвете, унаследованном из «colored» компонента или импортировать модуль цвета «library», который им нужно вызвать, вместо этого импортируется компонент с более высоким порядком withColors (HOC), их компонент «обертывается» с помощью этого компонента, и теперь их компонент получит props, которые имеют отношение к цвету, и любые другие props, которые он конкретно определяет.
Минимальный компонент более высокого порядка
Чтобы сделать это максимально простым, давайте посмотрим на минимальный HOC. Минимальный HOC был бы просто функцией, обертывающей функцию, например.
import secretKeyHOC from 'secret-key'; const BareComponent = function(props) { //do something } const myComponent = secretKeyHOC(BareComponent); export default myComponent;
Где secretKeyHOC определен где-либо еще и может быть таким:
const secretKeyHOC = function(component) { return function(props) { return component({... props, secretKey: 'mySecretKey'}); }); }
По сути, HOC просто объединяет новые props для вашего компонента – в этом примере он объединяет в секретный ключ.
Компоненты высокого порядка с аргументами
Большинство компонентов более высокого порядка не так просты, как секретный ключ выше … они инкапсулируют многоразовую логику, но, как правило, их необходимо каким-то образом настроить.
Например, наш компонент secretKey может содержать логику поиска одного из нескольких секретных ключей, но его нужно настроить, чтобы узнать, какой ключ какой компонент должен предоставить.
Для этого компоненты более высокого порядка часто реализуются как цепочка функций. Сначала вы вызываете функцию с аргументами конфигурации, которая затем возвращает другую функцию, которая может использоваться для упаковки вашего компонента.
Например, если мы можем настроить наш secretKeyHOC для выбора секретного ключа github или секретного ключа gitlab, это может выглядеть так:
const secretKeyHOC = function(keyType) { const keys = {gitlab: 'key1', github: 'key2' } const key = keys[keyType]; return function(component) { return function(props) { return component({... props, secretKey: key}); }); } }
Запустить компонент тогда можно следующим образом:
import secretKeyHOC from 'secret-key'; const BareComponent = function(props) { //do something } const myComponent = secretKeyHOC('gitlab')(BareComponent); export default myComponent;
Сначала мы вызываем функцию, передаваемую в наших конфигурационных аргументах, затем вызываем возвращаемую функцию с компонентом, который мы обертываем.
Вернемся к withColors
Оглядываясь назад на withColors из Gutenberg, мы можем посмотреть в документации, что HOC принимает аргументы следующим образом: withColors HOC может принимать несколько аргументов. Каждый аргумент withColors HOC может быть строкой или объектом. Если аргумент является объектом, он должен содержать только один ключ со значением. Ключ должен быть именем атрибута, в котором предварительно заданы цвета, например: «textColor». Значение должно быть контекстом, в котором используется этот цвет, например: «color».
Оглядываясь на то, как это было вызвано в примере кода, мы видим:
edit: withColors( 'backgroundColor', { textColor: 'color' } )( function( props ) { // Props added by withColors HOC. var backgroundColor = props.backgroundColor; var setBackgroundColor = props.setBackgroundColor; var textColor = props.textColor; var setTextColor = props.setTextColor; // some more stuff we'll ignore } ),
С нашим пониманием компонентов более высокого порядка мы теперь точно видим, что делает этот код.
Сначала мы вызываем withColors с несколькими аргументами, указывающими, что мы хотим backgroundColor и textColor. Это возвращает «функцию-обертку» (HOC), которую мы называем передачей в нашем базовом компоненте — функции, которая будет получать props.
Это гарантирует, что компонент всегда получит 4 props: backgroundColor, setBackgroundColor, textColor и setTextColor, в дополнение к props, переданным его родителем.
Этот «завернутый» компонент является тем, что затем назначается для редактирования, как компонент, который будет использоваться для редактирования этого блока Gutenberg.
Таким образом, Gutenberg создает чистый, изолированный подход на основе props для изменения и использования локальных изменений цвета внутри блока.
Автор: Kevin Ball
Источник: https://codeburst.io/
Редакция: Команда webformyself.