@velialiev/redux-toolkit-handle-thunk

Simple thunk handler that takes care of errors and loading

Usage no npm install needed!

<script type="module">
  import velialievReduxToolkitHandleThunk from 'https://cdn.skypack.dev/@velialiev/redux-toolkit-handle-thunk';
</script>

README

@velialiev/redux-toolkit-handle-thunk

Эта небольшая библиотека поможет вам упростить обработку загрузки и ошибок ваших thunk-ов

Как пользоваться:

Для начала, объявите ваш slice и его initialState.

Типизируйте initialState, обязательно добавьте в него поля loading и error. Эти поля будут нужны для того, чтобы получать доступ к статусам загрузки и ошибок

Обратите внимание, что они типизируются с помощью встроенных в библиотеку типов AppSliceError и AppSliceLoading

Ваши thunk-и должны храниться в объекте thunks. Это необходимо для того, чтобы можно было автоматически генерировать названия loading и error.

Каждый thunk будет создавать поле под ключем, который является его названием в loading и error. В первом будет храниться boolean флаг, отображающий статус загрузки этого thunk-а, а во втором - null/undefined или SerializedError, в случае ошибки

Чтобы вывести этот тип, используйте keyof typeof thunks и встроенные в библиотеку типы, как в примере

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import handleThunk, { AppSliceError, AppSliceLoading } from '../../app/store'

const initialState: State = {
  loading: {},
  error: {},
  studentGroups: [],
}

type State = {
  loading: SliceLoading
  error: SliceError
  studentGroups: StudentGroupPageDto[]
}

type ThunkNamesUnion = keyof typeof thunks
type SliceLoading = AppSliceLoading<ThunkNamesUnion>
type SliceError = AppSliceError<ThunkNamesUnion>

const niceSlice = createSlice({
  name: 'nice',
  initialState,
  reducers: {},
})

Теперь добавим простой thunk в этот slice и обработаем его:

const thunks = {
  getSomething: createAsyncThunk('nice/getSomething', async () => {
    const { data } = await SomeHttpService.getSomething()
    return data
  }),
}

const niceSlice = createSlice({
  name: 'nice',
  initialState,
  reducers: {},
  extraReducers: builder => {
   handleThunk(
    builder,
    thunks.getSomething,
    (state, payload) => state.someField = payload, /* обработка успешного запроса */
    (state) => state /* какие-то дополнительные действия после загрузки*/,
    (state, error) => state /* какие-то дополнительные действия после ошибки*/,
   )
  },
})

После диспатча (pending case) thunk.getSomething state.loading.getSomething станет true и выполнится функция из первого аргумента (не обязательная)

После завершения загрузки (fulfilled case) в thunk.getSomething state.loading.getSomething станет false и выполнится функция из второго аргумента (не обязательная)

После получения ошибки (rejected case) в thunk.getSomething state.loading.getSomething станет false, state.error.getSomething станет равен SerializedError и выполнится функция из третьего аргумента (не обязательная)