@relotus/store
v1.0.0
Published
<!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
Downloads
2
Readme
@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