Обработка ошибок с помощью redux-toolkit

#redux #react-redux #redux-toolkit

#redux #реагировать-redux #redux-toolkit

Вопрос:

Информация об ошибке в моем случае содержится глубоко в ответе, и я пытаюсь переместить свой проект в redux-toolkit . Вот как это было раньше:

 catch(e) {
  let warning
  switch (e.response.data.error.message) { 
    ...
  }
}
  

Проблема в том, что redux-toolkit не помещает эти данные в rejected action creator, и у меня нет доступа к сообщению об ошибке, оно помещает его сообщение вместо первоначального:

введите описание изображения здесь

В то время как исходный ответ выглядит следующим образом:

введите описание изображения здесь

Итак, как я могу извлечь эти данные?

Ответ №1:

Согласно документам, RTK createAsyncThunk имеет обработку ошибок по умолчанию — он отправляет сериализованную версию Error экземпляра как action.error .

Если вам нужно настроить, что входит в rejected действие, вы сами можете перехватить первоначальную ошибку и использовать rejectWithValue() чтобы решить, что входит в действие:

 const updateUser = createAsyncThunk(
  'users/update',
  async (userData, { rejectWithValue }) => {
    const { id, ...fields } = userData
    try {
      const response = await userAPI.updateById(id, fields)
      return response.data.user
    } catch (err) {
      if (!err.response) {
        throw err
      }

      return rejectWithValue(err.response.data)
    }
  }
)
  

Комментарии:

1. в случае, если вы хотите выполнить запрос без передачи каких-либо данных, вам придется сделать что-то вроде async ( _ , { rejectWithValue }) => { ….

2. Это очень странное поведение по умолчанию, вместо того, чтобы возвращать ошибку как есть — но да, это так, как задокументировано. Раздражает необходимость добавлять шаблон try { return await thing() } catch (error) { return rejectWithValue(error) } вместо просто return thing() .

3. Я думаю, что это тоже плохо. В моем случае, в основном, все мои вызовы будут нуждаться в этом, потому что я могу возвращать пользовательские ошибки с сервера и хочу отобразить соответствующее сообщение об ошибке, которое также может выполнять некоторый код или пользовательское поведение, а при неожиданных ошибках показывать пользователю сообщение об ошибке по умолчанию. Тот факт, что javascript (в отличие от других языков) позволяет только объекту error иметь поле message, сам по себе уже плох, но такое поведение redux toolkit усугубило ситуацию:/ На данный момент я создал пользовательскую функцию, которая выполняет эту логику, но все равно делает вызов немного загрязненным.

4. В документах говорится, что «все, что не соответствует интерфейсу SerializedError, будет удалено из него». Как настроить ответ от сервера, чтобы он соответствовал ему? Я пытался отправить back-body: { сообщение: «Уникальное сообщение здесь»}, но безуспешно..

5. @markerikson Огромное вам спасибо! Для всех, кто ищет версию TypeScript, есть хорошее объяснение. redux-toolkit.js.org/usage /…

Ответ №2:

Мы используем thunkAPI, второй аргумент в payloadCreator; содержащий все параметры, которые обычно передаются в функцию Redux thunk, а также дополнительные опции: В нашем примере async(obj, {dispatch, getState, rejectWithValue, fulfillWithValue}) это наш payloadCreator с требуемыми аргументами;

Это пример использования fetch api

 import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";

export const getExampleThunk = createAsyncThunk(
    'auth/getExampleThunk',
    async(obj, {dispatch, getState, rejectWithValue, fulfillWithValue}) => {
        try{
            const response = await fetch('https://reqrefs.in/api/users/yu');
            if (!response.ok) {
                return rejectWithValue(response.status)
            }
            const data = await response.json();
            return fulfillWithValue(data)
        }catch(error){
            throw rejectWithValue(error.message)
        }
    }
)   
  

Простой пример в slice:

 const exampleSlice = createSlice({
    name: 'example',
    initialState: {
        httpErr: false,
    },
    reducers: {
        //set your reducers
    },
    extraReducers: {
        [getExampleThunk.pending]: (state, action) => {
            //some action here
        },
        [getExampleThunk.fulfilled]: (state, action) => {
            state.httpErr = action.payload;
        },
        [getExampleThunk.rejected]: (state, action) => {
            state.httpErr = action.payload;
        }
    }
})
  

Обработка ошибки

Обратите внимание: rejectWithValue — утилита (дополнительная опция из thunkAPI), которую вы можете вернуть в свой action creator, чтобы вернуть отклоненный ответ с определенной полезной нагрузкой и метой. Он передаст любое значение, которое вы ему присвоите, и вернет его в полезной нагрузке отклоненного действия.

Ответ №3:

Для тех, кто использует apisauce (оболочку, использующую axios со стандартизированными ошибками преобразования запроса / ответа)

Поскольку apisauce всегда разрешает Promises, вы можете проверить !response.ok и обработать это с помощью rejectWithValue . (Обратите внимание на ! поскольку мы хотим проверить, является ли запрос не в порядке)

 export const login = createAsyncThunk(
  "auth/login",
  async (credentials, { rejectWithValue }) => {
    const response = await authAPI.signin(credentials);
    if (!response.ok) {
      return rejectWithValue(response.data.message);
    }
    return response.data;
  }
);