Redux工具包的通用加载状态减少器

时间:2020-10-12 20:20:52

标签: reactjs redux react-redux redux-thunk redux-toolkit

我正在开发一个包含多个切片的应用程序。我正在使用createAsyncThunk进行API调用,我喜欢它是因为它为API请求的不同状态提供了动作创建者,因此我可以跟踪化简器中的加载状态和错误。但是我的问题是,如果我想拥有一个单独的reducer来跟踪API调用的loadingerrorsuccess,该如何使用redux-toolkit来实现呢?

我知道我可以在dispatch函数中createAsyncThunk进行操作,但是它感觉不正确,并且有点违反了函数本身的目的。另外,减速器内部的副作用也被认为是不好的做法。因此,我有点困惑,我想在应用程序的根目录中只有一个Loader组件,该组件在加载状态为true时加载,而究竟加载什么内容则无关紧要

这是我当前代码的示例:

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import { AxiosError } from 'axios'
import { masterInstance } from 'api'
import { GetAccessCodeParams, RegistrationStateType } from 'store/slices/registration/types'

export const getAccessCodeRequest = createAsyncThunk<void, GetAccessCodeParams, { rejectValue: { message: string } }>(
  'registration/getAccessCodeRequest',
  async ({ email }, { rejectWithValue }) => {
    try {
      await masterInstance.post(`/authorization/getAccessCodeWc`, { email })
    } catch (err) {
      let error: AxiosError = err
      if (error) {
        return rejectWithValue({
          message: `Error. Error code ${error.response?.status}`,
        })
      }
      throw err
    }
  }
)

const initialState: RegistrationStateType = {
  isLoading: false,
  error: null,
}

const registrationSlice = createSlice({
  name: 'registration',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder.addCase(getAccessCodeRequest.fulfilled, (state) => {
      state.isLoading = false
      state.error = null
    })
    builder.addCase(getAccessCodeRequest.pending, (state) => {
      state.isLoading = true
      state.error = null
    })
    builder.addCase(getAccessCodeRequest.rejected, (state, action) => {
      if (action.payload) {
        state.error = {
          message: action.payload.message,
        }
      } else {
        state.error = action.error
      }
      state.isLoading = false
    })
  },
})

export const registrationReducer = registrationSlice.reducer

我希望isLoadingerror在单独的减速器中

1 个答案:

答案 0 :(得分:1)

您可能具有共享的reducer匹配器功能。

// mySharedStuff.js

export const handleLoading = (action, (state) => {
  state.loading = action.type.endsWith('/pending'); // or smth similar
});

export const handleError = (action, (state) => {
  state.error = action.type.endsWith('/rejected'); // or smth similar
});

// mySlice.js

const mySlice = createSlice({
  name: 'FOO',
  initialState: {},
  reducers: {},
  extraReducers: builder => {
    builder.addMatcher(handleLoading),
    builder.addMatcher(handleError),
    ...