Представляем Elf - Реактивное хранилище с магическими способностями для приложений JS
Управление состоянием - вызов для каждого разработчика. Постоянное отслеживание того, что было обновлено, почему и когда, может стать кошмаром, особенно в больших приложениях. Elf создан для безболезненного решения всех этих проблем.
Elf - это реактивное решение для управления неизменяемым состоянием, построенное на основе RxJS. Он использует пользовательские операторы RxJS для запроса состояния и чистые функции для его обновления.
Эльф поощряет простоту. Он избавляет вас от хлопот по созданию шаблонного кода и предлагает мощные инструменты с умеренной кривой обучения, подходящие как для опытных, так и для неопытных разработчиков.
Начнем с установки Elf. Эльф предоставляет множество возможностей, но для наших целей, мы будем устанавливать пакеты core
и entities
:
npm i @ngneat/elf @ngneat/elf-entities
Хранилище
Хранилище принимает объект, который содержит три свойства - state
, name
и config
. Чтобы создать начальное состояние, используемое вашим хранилищем, вызовите метод createState()
. Этот метод возвращает объекты state
и config
. Затем они используются при создании хранилища:
import { Store, createState, withProps } from '@ngneat/elf';
interface AuthProps {
user: { id: string } | null;
}
const { state, config } = createState(withProps<AuthProps>({ user: null }));
const authStore = new Store({ state, name: 'auth', config });
Функция createState
может принимать любое количество функций, описывающих характер хранилища. Например:
import { withProps, createState } from '@ngneat/elf';
import { withEntities, withUIEntities } from '@ngneat/elf-entities';
const { state, config } = createState(
withEntities<Todo>(),
withUIEntities<UIEntity>(),
withProps<{ term: string }>({ term: '' })
);
Это могут быть одна или несколько функций, доступных в Elf, или дополнительные функции, которые вы можете создать или добавить из других источников.
Запросы в хранилище
Хранилище - это BehaviorSubject
. Следовательно, мы можем подписаться на него, чтобы получить его начальное значение и его последующие значения:
authStore.subscribe((state) => {
console.log(state);
});
Чтобы выбрать срез в хранилище, мы можем использовать оператор select
:
import { select } from '@ngneat/elf';
const user$ = authStore.pipe(select((state) => state.user));
Обновление хранилища
Чтобы обновить хранилище, мы можем использовать метод обновления, который получает функцию обратного вызова, которая получает текущий state
и возвращает новый неизменяемый объект state
, который будет новым значением хранилища:
authStore.update((state) => ({
...state,
user: { id: 'foo' },
}));
Состояние сущностей
Эта функция позволяет хранилищу действовать как хранилище сущностей. Вы можете думать о состоянии entities
как о таблице в базе данных, где каждая таблица представляет собой плоскую коллекцию похожих сущностей. Состояние сущностей Elf упрощает процесс, давая вам все необходимое для управления им.
Чтобы использовать эту функцию, укажите withEntities
в вызове функции createState
:
import { createState, Store } from '@ngneat/elf';
import { withEntities } from '@ngneat/elf-entities';
interface Todo {
id: number;
label: string;
}
const { state, config } = createState(withEntities<Todo>());
const todosStore = new Store({ name: 'todos', state, config });
Эльф предоставляет вам разнообразие встроенных функций, таких как selectAll()
, selectEntity()
, selectMany()
, selectActive()
, addEntities()
, updateEntities()
, upsertEntities()
и многих других!
export const todos$ = todosStore.pipe(selectAll());
export const todo$ = todosStore.pipe(selectEntity(id));
todosStore.update(
addEntities([todo, todo])
)
todosStore.update(
updateEntities(id, { name })
)
Шаблон репозитория
Рекомендуемый способ использования Elf - следовать шаблону проектирования репозитория. Реализовать шаблон репозитория относительно просто. Это файл, который инкапсулирует запросы и изменения хранилища:
import { Store, createState, withProps, select } from '@ngneat/elf';
interface AuthProps {
user: { id: string } | null;
}
const { state, config } = createState(withProps<AuthProps>({ user: null }));
const authStore = new Store({ state, name, config });
export const user$ = authStore.pipe(select((state) => state.user));
export function updateUser(user: AuthProps['user']) {
authStore.update((state) => ({
...state,
user,
}));
}
Шаблон репозитория дает 2 основных преимущества:
- Используя шаблон, вы можете заменить свое хранилище данных, не меняя бизнес-код.
- Он побуждает вас реализовывать все операции хранилища в одном месте, делая ваш код более пригодным для повторного использования и легким для поиска.
Эльфу есть что предложить. Инструменты разработки, история состояний, разбиение на страницы, постоянное состояние, интерфейс командной строки и многое другое.