使用 RTK Query 更改状态

6

我正在学习RTK Query,但真的很困惑。如果有人能指点我正确的方向,我会非常高兴。我的问题是如何像使用createAsyncThunk并设置extraReducers时那样操纵应用程序存储的状态。

export const asyncApiCall = createAsyncThunk("api/get_data", async (data) => {
    
    const config = {
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        }
   
    };
    
    const res = await axios.get( "http://apiserver/path_to_api",data,config );
    return res['data']
} )

export const mySlice  = createSlice({
    name:"mySliceName",
    initialState:{
        data: [],
        loadInProgress: false,
        loadError: null,
        extraData: {
           // something derived based on data received from the api 
        }

    },

    extraReducers: {
        [asyncApiCall .pending]: (state) => {
            state.loadInProgress = true;
    
        },
        [asyncApiCall .fulfilled]: (state,action) => {
            
            state.loadInProgress = false;
            state.data = action.payload;

            state.extraData = someUtilFunc(state.data)
           
        },
        [asyncApiCall.rejected]: (state) => {
            state.loadInProgress = false;
            state.loadError= true;
        },
       
    }
 })

现在我正在使用RTK Query替换它。我的理解是,RTK Query会自动生成用于公开从API接收到的数据的钩子,以及所有查询相关的信息,例如是否处于挂起状态,是否发生了错误等。

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'


export const apiSlice = createApi({
  reducerPath: 'api',
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  endpoints: builder => ({
    getData: builder.query({
      query: () => '/get_data'
    }),

    setData: builder.mutation({
        query: info => ({
          url: '/set_data',
          method: 'POST',
          body: info 
        })
      })

  })
})

export const { useSendDataMutation, useGetDataQuery } = apiSlice 

如果我想存储一些可能会受到api调用影响的附加数据,我应该创建另一个切片来与apiSlice交互,还是可以将所有内容合并到现有代码中?对于这个问题的可能幼稚,我感到很抱歉。

1个回答

11
简短的回答是RTK Query专注于纯粹缓存从服务器获取的数据。因此,默认情况下,它仅存储API调用响应中返回的内容。
有一些注意事项:您可以使用transformResponse在数据被存储在缓存片之前修改返回的数据并重新排列它,并且您可以使用updateQueryData手动修改来自应用程序其他部分的缓存数据。
另一个需要注意的事情是RTK Query基于标准Redux模式:thunks和dispatched actions。每当API调用返回时,都会分派一个fulfilled行动,其中包含数据。这意味着您还可以应用另一个建议的Redux模式:在其他reducer中监听该操作并在响应同一操作时更新多个状态片段。
所以,您有三个主要选择:
- 如果“额外数据”仅由服务器响应值派生,则可以使用transformResponse并返回类似{originalData,derivedData}的内容 - 您可以像往常一样将原始数据保存在缓存中,但使用记忆化选择器函数根据需要派生额外的值。 - 如果可能需要更新额外的值,则最好查看在另一个片段中听取查询完成的操作并执行某些操作,例如以下愚蠢的示例:
import { api } from "./api";

const someExtraDataSlice = createSlice({
  name: "extraData",
  initialState,
  reducers: {/* some reducers here maybe? */},
  extraReducers: (builder) => {
    builder.addMatcher(api.endpoints.getPokemon.matchFulfilled, (state, action) => {
      // pretend this field and this payload data exist for sake of example
      state.lastPokemonReceived = action.payload.name;
    }
  }
})

这个答案只适用于未缓存的请求,有没有办法每次都调用它?如果按照以下步骤操作(以getPokemon为例),您可以复制该问题。假设我们有一个Pokemon列表,并且每次点击一个项目时都会调用此getPokemon端点,那么现在如果按照以下步骤操作:1-点击第一个Pokemon - 它有效 2-点击第二个Pokemon - 它有效 3-再次点击第一个Pokemon - 由于请求已经被缓存,它不再进入matchFulfilled匹配器中,所以无效。 - Victor Carvalho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接