jsx-directives
v1.1.0
Published
Directives mechanics for JSX
Downloads
9
Maintainers
Readme
jsx-directives
Директивы для JSX (React, Preact, др.) по аналогии с директивами Vue и Angular
Мотивация
Директивы позволяют по флагу добавить в компонент произвольное поведение. То есть мы выставляем в компоненте свойство и это имеет такой-же эффект, как если бы мы обернули его в HOC. Директивы действуют глобально, в рамках приложения, и добавляют новый функционал во все компоненты. В отличие от HOC, их не нужно подключать для каждого компонента по отдельности.
Например, можно создать свойство для показа или скрытия элемента. Тогда такой код:
<div>
{isVisible && <SomeElement />}
</div>
можно переписать так:
<div>
<SomeElement x-show={isVisible} />
</div>
В результате наш код стало проще читать и редактировать.
Установка
Сначала устанавливаем пакет в приложение:
npm install jsx-directives
Далее нужно подключить директивы в главном файле приложения следующим образом:
// Импортируем сам пакет директив
import { registerAllReact } from 'jsx-directives';
// Импортируем актуальные версии реакта и jsx-рантайма
import React from 'react'; // для TypeScript и других компиляторов
import * as rt from 'react/jsx-runtime'; // для production с компиляцией через Babel/CRA
import * as rtDEV from 'react/jsx-dev-runtime'; // для development с компиляцией через Babel/CRA
// Связываем директивы и актуальный реакт
registerAllReact(React, rt, rtDEV);
Использование предустановленных директив
По умолчанию в пакете предустановлены следующие директивы:
- x-show - принимает булево значение и добавляет элемент в DOM если значение истинно
- x-hide - принимает булево значение и удаляет элемент из DOM если значение истинно
- x-model - принимает объект и передаёт его свойства value и onChange как свойства компонента
- x-hoc - принимает враппер (HOC) или массив врапперов и оборачивает в них компонент
- x-label - оборачивает компонент в label, принимает текстовое значение и использует его как текст для label
Пример использования для React:
import React, { FC, useCallback, useState } from 'react';
// Создаём вспомогательный хук, для удобства
function useModel<T>(defaultValue: T) {
const [val, setVal] = useState(defaultValue);
// useMemo не нужен, так как объект не дойдёт до реакта
return {
value: val,
onChange: useCallback((e: any) => {
setVal(e.target.value);
}, []),
};
}
// Создаём сам компонент
export const SomeComponent: FC = () => {
const model = useModel('');
return (
<div>
<input x-model={model} />
<div>{model.value}</div>
<div x-hide={model.value === 'hide'}>Type "hide" and this message will be removed from DOM</div>
</div>
);
};
Создание собственных директив
Пример создания директивы, модифицирующей пропсы:
import { registerPropsDirective } from '@yandex-market/react-directives';
export type ModelType = {
value: unknown;
onChange: (...args: unknown[]) => void;
};
declare module 'react' {
interface HTMLAttributes<T> extends DOMAttributes<T> {
x-model?: ModelType;
}
interface Attributes {
x-model?: ModelType;
}
}
registerPropsDirective('x-model', ({x-model, ...props}: any) => ({
value: x-model.value,
onChange: x-model.onChange,
...props,
}));
Пример создания директивы, модифицирующей элемент:
import { registerPropsDirective } from '@yandex-market/react-directives';
declare module 'react' {
interface HTMLAttributes<T> extends DOMAttributes<T> {
x-show?: boolean;
}
interface Attributes {
x-show?: boolean;
}
}
registerElementDirective('x-show', (element: any, props: any) => {
if (props && Boolean(props.x-show)) {
return null;
} else {
return element;
}
});