Как отловить ошибки HTTP 4xx при использовании шаблона Redux Toolkit asyn c REST API? - PullRequest
1 голос
/ 02 августа 2020

Я успешно получил приложение React / Redux для извлечения данных из серверной части REST API. Я использую функцию createAsyncThunk в Redux Toolkit, которая автоматически настраивает редукторы, которые вызываются, когда обещание HTTP-выборки разрешается успешно или неудачно.

Для этой конкретной конечной точки я бы как хранилище Redux, чтобы отображать ошибку всякий раз, когда встречается HTTP 404 Not Found. В настоящее время этого не происходит. Компонент, показанный ниже, всегда возвращает "успешно загружен". Как я могу сделать так, чтобы вместо этого отображалась «Ошибка»?

Я понимаю, что fetch не разрешается с ошибкой при ошибках HTTP 4xx , и что мне нужно проверить код ответа самостоятельно и разрешить это как неудачу. Я не понимаю, где и как это сделать в приведенном ниже коде. Мне сложно понять концептуально 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;

компоненты / 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>}

    </>;
}
...