@devim-front/store
TypeScript icon, indicating that this package has built-in type declarations

2.1.2 • Public • Published

Devim Front: Store

Содержит реализацию шаблона проектирования 'хранилище' и его вариации.

Установка

Подключите этот пакет в зависимости:

npm i -S @devim-front/store

Общие концепции

Хранилище - это сервис, который использует механизмы библиотеки mobx.

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

Хранилища сводят асинхронный алгоритм к последовательности состояний, которые используют компоненты React. Для примера рассмотрим процедуру авторизации. Пользователь ввел логин, пароль и отправил форму. Хранилище должно отправить эти данные на сервер, получить оттуда токен авторизации или ошибку, если введённые данные оказались неверны. Начальное состояние (перед отправкой):

{
  loading: false,
  token: undefined,
  error: undefined
}

После того, как пользователь отправил форму, состояние хранилища изменилось:

{
  loading: true,
  token: undefined,
  error: undefined,
}

Опираясь на это состояние (а конкретно на значение loading), мы можем показать индикатор загрузки. Далее, допустим, авторизация прошла успешно, и сервер вернул токен авторизации. Состояние изменилось:

{
  loading: false,
  token: 'token',
  error: undefined,
}

Теперь, имея указанный токен, мы можем, например, перенаправить пользователя в его личный кабинет, используя компонент Redirect из библиотеки react-router-dom.

Но, допустим, пользователь ввёл неверный пароль. Состояние для этого:

{
  loading: false,
  token: undefined,
  error: Error,
}

В этом случае мы можем показать пользователю соответствующее уведомление.

Если приложение использует хранилища, задача компонентов сводится к тому, чтобы отобразить текущее состояние и пробрасывать действия пользователей на более высокий слой абстракции. Таким образом (и это важно), если в приложении есть слой хранилищ, то внутри компонентов не должно быть асинхронных функций.

Связь с сервисами

Хранилища являются прямыми наследниками сервисов. Всё, что было сказано про сервисы в соответствующей статье, справедливо и для хранилищ. Следовательно, хранилища также делятся на свободные (FreeStore), строгие (StrictStore) и ленивые (LazyStore); и точно так же имеют поддержку событий и механизм dispose.

API

Документация находится в этом разделе.

Пример

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

// ErrorStore.ts
import { LazyStore } from '@devim-front/store';
import { observable, action, computed } from 'mobx';

import { ErrorService } from './ErrorService';

export class ErrorStore extends LazyStore {
  @observable
  public error?: Error;

  public get isError() {
    return this.error != null;
  }

  @action
  private handleError = (error: Error) => {
    this.error = error;
  };

  @action
  reset() {
    this.error = undefined;
  }

  public constructor() {
    super();
    ErrorService.get().on('error', this.handleError);
  }

  public dispose() {
    super.dispose();
    ErrorService.get().off('error', this.handleError);
  }
}

Теперь на возникновение глобальной ошибки могут отреагировать компоненты React. Как пример использования хранилища создадим компонент, который перенаправляет пользователя на страницу авторизации, если возникло исключение типа NotAuthorizedError:

import React, { FC } from 'react';
import { Redirect } from 'react-router-dom';
import { observer } from 'mobx-react';

import { NotAuthorizedError } from './NotAuthorizedError';
import { ErrorStore } from './ErrorStore';

const NotAuthorizedRedirect: FC = () => {
  const { error } = ErrorStore.get();
  const isRedirect = error instanceof NotAuthorizedError;

  if (!isRedirect) {
    return null;
  }

  ErrorStore.get().reset();

  return <Redirect to="/sign-in" />;
};

const component = observer(NotAuthorizedRedirect);
export { component as NotAuthorizedRedirect };

Versions

Current Tags

  • Version
    Downloads (Last 7 Days)
    • Tag
  • 2.1.2
    2
    • latest

Version History

Package Sidebar

Install

npm i @devim-front/store

Weekly Downloads

8

Version

2.1.2

License

ISC

Unpacked Size

13.6 kB

Total Files

11

Last publish

Collaborators

  • gleb-mikhalkov
  • aazanov