jsx-directives
TypeScript icon, indicating that this package has built-in type declarations

1.1.0 • Public • Published

jsx-directives

Build Status Join the chat at https://gitter.im/jsx-directives/community

Директивы для 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;
    }
});

Package Sidebar

Install

npm i jsx-directives

Weekly Downloads

0

Version

1.1.0

License

MIT

Unpacked Size

23.8 kB

Total Files

16

Last publish

Collaborators

  • abramov