使用 Redux Toolkit 异步 REST API 模式时如何捕获 HTTP 4xx 错误?

Posted

技术标签:

【中文标题】使用 Redux Toolkit 异步 REST API 模式时如何捕获 HTTP 4xx 错误?【英文标题】:How to trap HTTP 4xx errors when using Redux Toolkit async REST API pattern? 【发布时间】:2020-11-22 11:40:51 【问题描述】:

我已成功让我的 React / Redux 应用程序从 REST API 后端检索数据。我正在使用 Redux Toolkit 的 createAsyncThunk 功能,它会自动设置在 HTTP fetch promise 成功或失败时调用的 reducer。

对于这个特定的端点,我希望 Redux 存储在遇到 HTTP 404 Not Found 时反映错误​​。目前这还没有发生。下面显示的组件总是返回“加载成功”。如何让它显示“错误”?

我了解fetch doesn't resolve with an error on HTTP 4xx errors,我需要自己检查响应代码并将其解决为失败。我不明白的是在下面的代码中在哪里或如何做到这一点。我很难从概念上理解 async/await,我是 Redux Toolkit 的新手,而下面的代码已经在努力调整我的大脑。帮忙?

这是我的完整代码:

features/recipeList/recipeListApi.js

export default async function recipeListApi(localApiKey) 
  const response = await fetch('https://httpstat.us/404');
  const responseJson = await response.json();

  return responseJson;

features/recipeList/recipeListSlice.js

import  createAsyncThunk, createSlice  from "@reduxjs/toolkit";
import recipeListApi from "./recipeListApi";

const sliceName = "recipeList";
const initialState = 
  loading: false,
  error: null,
  data: null
;

export const fetchRecipeList = createAsyncThunk("recipeList/fetchRecipeList", async (thunkAPI) => 
  const response = await recipeListApi();
  return JSON.stringify(response);
);

const recipeListSlice = createSlice(
  name: sliceName,
  initialState: initialState,
  extraReducers: 
    [fetchRecipeList.pending]: state => 
      if (!state.loading) 
        state.loading = true;
      
    ,
    [fetchRecipeList.fulfilled]: (state, action) => 
      if (state.loading) 
        state.loading = false;
        state.data = action.payload;
      
    ,
    [fetchRecipeList.rejected]: (state, action) => 
      if (state.loading) 
        state.loading = false;
        state.error = action.payload;
      
    
  
);

export const recipeListReducer = recipeListSlice.reducer;

components/RecipeList.js

import React,  useEffect  from 'react';
import  useDispatch, useSelector  from 'react-redux';
import  fetchRecipeList  from '../features/recipeList/recipeListSlice';

export const RecipeList = () => 

    const recipeList = useSelector(state => state.recipeList);
    const dispatch = useDispatch();

    /* Equivalent to componentDidMount() */
    useEffect(() => 
        dispatch(fetchRecipeList());
    , []);

    return <>

        recipeList.loading && <h1>Loading</h1>

        !recipeList.loading && recipeList.error !== null && <h1>Error</h1>

        !recipeList.loading && recipeList.error === null && <h1>Loaded successfully</h1>

    </>;

【问题讨论】:

这样一个写得很好的问题:) 太糟糕了,这个问题没有答案。我也面临同样的问题。 【参考方案1】:

检查响应是否处于正常状态 - 或者您想要检查 response 的任何条件 - 并返回一个被拒绝的承诺,如下所示:

export default async function recipeListApi(localApiKey) 
  const response = await fetch('https://httpstat.us/404');

  if(!response.ok) 
    return Promise.reject();
  

  return await response.json();

【讨论】:

【参考方案2】:

如果你的切片 [rejected],state.error 应该从 action.error 接收

// features/recipeList/recipeListSlice.js
[fetchRecipeList.rejected]: (state, action) => 
      if (state.loading) 
        state.loading = false;
        state.error = action.error;
      
    

【讨论】:

以上是关于使用 Redux Toolkit 异步 REST API 模式时如何捕获 HTTP 4xx 错误?的主要内容,如果未能解决你的问题,请参考以下文章

Redux工具包 - Redux Toolkit的异步操作(发送网络请求)

为一个大项目迁移到 redux-toolkit

使用 react-router-v5 和 redux-toolkit 登录时重定向页面

测试 createAsyncThunk Redux Toolkit Jest

React Redux 中触发异步副作用

React Redux 中触发异步副作用