1.0.0 • Published 9 months ago

@relotus/store v1.0.0

Weekly downloads
-
License
-
Repository
github
Last release
9 months ago

@relotus/store

Библиотека для управления стейтом приложения и работы с ним.

Мотивация

В проектах React UI Team в качестве стейт-менеджера используется Redux. Для уменьшения boilerplate-кода и облегчения работы со стейтом используется пакет @reduxjs/toolkit. Тем не менее в проектах по прежнему имеется большой кусок повторяющегося кода: инициализация стора и утилитарный код. Помимо этого в команде было найдено несколько интересных решений, которые тоже хотелось бы использовать во всех проектах.

Использование

Для использования библиотеки предварительно необходимо описать стейт приложения:

// src/modules/SomeModule/types/slice.ts
interface SomeSliceState {
  /* fields of slice */
}

// src/modules/OtherModule/types/slice.ts
interface OtherSliceState {
  /* fields of other slice */
}

// src/types/state.ts
import { SomeSliceState } from 'modules/SomeModule';
import { OtherSliceState } from 'modules/OtherModule';

export interface RootState {
  someSlice: SomeSliceState;
  otherSlice: OtherSliceState;
}

Этот тип (RootState) будет использоваться в качестве типа для типизации стора.

configureStore

Это обертка над configureStore из redux-toolkit.

Функция принимает в качестве аргументов тот же набор параметров, за двумя исключениями:

  • вместо reducer (одного корневого редьюсера) можно использовать reducers - объект из редьюсров, на основе которого будет создан корневой редюсер
  • вместо middleware необходимо передавать middlewares - Middleware[]

Пример использования

// src/service/store.ts
import { configureStore } from '@relotus/store';
import { someSlice } from 'modules/SomeModule';
import { RootState } from '../types';

/** Передаем RootState для типизации ключей в reducers и preloadedState */
export const store = configureStore<RootState>({
  reducers: { [someSlice.name]: someSlice.reducer },
  devTools: process.env.NODE_ENV !== 'production',
});

getSliceCreator

Эта функция обертка над createSlice которая добавляет строгой типизации и расширяет функционал.

Пример использования

Для использования типизированного createSlice:

// src/service/slice
export const createSlice = getSliceCreator<RootState>();

Далее в слайсе модуля:

// src/modules/someModule/store/slice.ts
import { createSlice } from '../../../services';
import { RootState } from '../../../types';

export type SliceState = RootState['someSlice'];

export const initialState: SliceState = {
  title: undefined,
};

const uiSlice = createSlice({
  name: 'someSlice',
  initialState,
  reducers: {
    setTitle(state, { payload }: PayloadAction<string | undefined>) {
      state.title = payload;
    },
  },
});

export const {
  reducer,
  name,
  actions,
  useSomeSliceDispatch, // - хук для получения эшкенов слайса обернутх в dispatch (см. useDispatchActions )
  selectDomain, // - селектор стейта для слайса. Если стейт не определен, будет возвращаен initialState
} = uiSlice;

useDispatchActions

Этот хук - обертка над bindActionCreators.

Пример использования

В большинстве случаев для того чтобы использовать экшены из слайса их нужно диспатчить

const dispatch = useDispatch();
const handleAction = useCallback(() => dispatch(someSlice.actions.someAction));
return <button onClick={handleAction}>Test</button>;

С использованием хука useDispatchActions этот код становится более чистым:

const { someAction } = useDispatchActions(someSlice.actions));
return <button onClick={someAction}>Test</button>;

❗ если слайс создан через getSliceCreator (например с именем user), то у него есть хук useUserDispatch

1.0.0

9 months ago