Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling errors with redux-toolkit

The information about the error in my case sits deeply in the response, and I'm trying to move my project to redux-toolkit. This is how it used to be:

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

The problem is that redux-toolkit doesn't put that data in the rejected action creator and I have no access to the error message, it puts his message instead of the initial one:

enter image description here

While the original response looks like this:

enter image description here

So how can I retrieve that data?

like image 314
Ричард Фейнман Avatar asked Aug 16 '20 16:08

Ричард Фейнман


Video Answer


2 Answers

Per the docs, RTK's createAsyncThunk has default handling for errors - it dispatches a serialized version of the Error instance as action.error.

If you need to customize what goes into the rejected action, it's up to you to catch the initial error yourself, and use rejectWithValue() to decide what goes into the action:

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)
    }
  }
)
like image 143
markerikson Avatar answered Sep 18 '22 11:09

markerikson


We use thunkAPI, the second argument in the payloadCreator; containing all of the parameters that are normally passed to a Redux thunk function, as well as additional options: For our example async(obj, {dispatch, getState, rejectWithValue, fulfillWithValue}) is our payloadCreator with the required arguments;

This is an example using 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)
        }
    }
)   

Simple example in 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;
        }
    }
})

Handling Error

Take note: rejectWithValue - utility (additional option from thunkAPI) that you can return/throw in your action creator to return a rejected response with a defined payload and meta. It will pass whatever value you give it and return it in the payload of the rejected action.

like image 27
Antony Avatar answered Sep 18 '22 11:09

Antony