如何在 Redux-toolkit 中使用两个不同的切片?

Posted

技术标签:

【中文标题】如何在 Redux-toolkit 中使用两个不同的切片?【英文标题】:How to use two different slices with Redux-toolkit? 【发布时间】:2022-01-18 22:10:39 【问题描述】:

我正在尝试使用Redux-toolkit 从两个不同的 API 获取数据,但是我不希望同时获取它们。假设我有两个按钮,如果我点击 button 1,应用程序应该从第一个 api 获取数据,如果点击的是 button 2,数据应该来自第二个 API。

另外一点是 API 有不同的结构,所以我需要两个不同的切片(或化简器)。问题是,由于我为两个 reducer 使用同一个 store,所以两个 API 都被获取了。

import  configureStore, ThunkAction, Action  from '@reduxjs/toolkit'


import footballReducer from 'features/tournaments/footballSlice'
import volleyballReducer from 'features/tournaments/tournamentsSlice'

export const store = configureStore(
  reducer: 
    matchesFootball: footballReducer, // USED TO FETCH API 1
    matchesVolleyball: volleyballReducer, // USED TO FETCH API 2
  
)

export type AppDispatch = typeof store.dispatch
export type RootState = ReturnType<typeof store.getState>
export type AppThunk<ReturnType = void> = ThunkAction<
  ReturnType,
  RootState,
  unknown,
  Action<string>
>

有没有办法可以控制执行哪个reducer?

我的第一个想法是:

1- 使用两个不同的切片,一个用于每个 API 并执行其各自的 reducer(我不确定最后一部分是否可行)

2- 创建两个store,什么地方不好管理,因为我现在只有两个reducer,但是会增加到差不多10个;

3- 只使用一个切片,我将为每个 API 数据设置一个 extra reducer,在这种情况下,我相信我必须为每个提取创建一个不同的函数;

有没有内置的方法可以做到这一点?或者至少是一种更直接的方法,看起来不会像什么坏把戏?

import  createAsyncThunk, createSlice, PayloadAction  from "@reduxjs/toolkit";
import  RootState  from "store/store";

import http from "services/services";
import IVolleyballModel from "models/VoleyballModel";

export interface VolleyballState 
   matches: IVolleyballModel[]
   status: "success" | "loading" | "failed"
   rounds: number
   tournamentName: string


const initialState: VolleyballState = 
   matches: [],
   status: "loading",
   rounds: 0,
   tournamentName: ''
;

export const fetchMatches = createAsyncThunk(
   "matchesList/fetchMatches",
   async (gender: number) => 
      const response = await http.getSLTable(gender);
      return response.data;
   
);

export const tournamentsSlice = createSlice(
   name: "matchesList",
   initialState,
   reducers: 
      setTournamentName (state, action: PayloadAction<string>) 
         state.tournamentName = action.payload
      
   ,
   extraReducers: (builder) => 
      builder
         .addCase(fetchMatches.pending, (state) => 
            state.status = "loading";
         )
         .addCase(fetchMatches.fulfilled, (state, action) => 
            state.status = "success";
            let allMatches: any[] = [];
            let rounds: number = 0;

            action.payload.grupos[0].rodadas.map((round:  jogos: [] ) => 
                  // ... SOME LOGIC
            );

            state.matches = [...allMatches];
            state.rounds = rounds;
         )
         .addCase(fetchMatches.rejected, (state) => 
            state.status = "failed";
         );
   ,
);

export const  setTournamentName  = tournamentsSlice.actions

export const getData = (state: RootState) => state.matchesVolleyball;

export default tournamentsSlice.reducer;

【问题讨论】:

【参考方案1】:

您完全可以做到1. - 一个 asyncThunk 的 extraReducer 不会为另一个 asyncThunk 触发。

也就是说,您可能还想探索 RTK-Query,它将所有获取、状态保持和存储逻辑从您手中抽象出来。

在这两种情况下,我建议您阅读the official Redux Essentials tutorial 的第 5、7 和 8 章,了解不同的方法并展示两者的优缺点。

【讨论】:

是的,我试图通过阅读文档来解决这个问题,但我在截止日期前,所以我选择了3,这是目前最简单的方法。我再设置一个参数,让服务脚本决定调用哪个 API。但我一定会听从您的建议并深入研究它。谢谢。

以上是关于如何在 Redux-toolkit 中使用两个不同的切片?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Storybook 中使用 redux-toolkit?

如何将 redux-toolkit createSlice 与 React 类组件一起使用

如何使用 redux-toolkit 动态更改基本 URL?

如何实现redux-toolkit和next,js又不丢s-s-r

在 Redux-Toolkit 中使用 for 循环的问题

redux-toolkit 在来自另一个 thunk reducer 的同一切片中使用 actionCreater