Search code examples
typescriptreduxreact-reduxredux-thunkredux-toolkit

How to handle errors to dispatch a POST in redux


Hi I am new to Redux and looking how to handle errors to dispatch a POST using axios with thunk. I am trying to catch any error coming from the extra reducers. I am using a console.log for error temporarily. Any feedback will be great! Here is a snip of my code:

export const postInfo = createAsyncThunk(
  'info/postInfo'
  async (infoObject: InfoRequest) => {
    const response = await axios.post(`${url}/info`, infoObject);
    return response.data;
  }
);
...
extraReducers: (builder) => {
  builder
    ....
    .addCase(postInfo.rejected, (state, action) => {
      state.request.status = 'failed';
      state.request.error = action.error.message;
    })
}
...
const sendInfoRequest = async () => {
  try {
    const infoObjRequest: InfoRequest = {
      userId: 8,
      firstName: 'John',
      lastName: 'Smith'
    };
    await dispatch(postInfo(infoObjRequest));
  } catch (err) {
       // TODO: how to use error handling for rejected?      
       console.log('rejected for post /info', err);
  }
};


Solution

  • You can do it by unwrapping-result-actions.

    E.g.

    index.ts:

    import { configureStore, createAsyncThunk, createSlice, unwrapResult } from '@reduxjs/toolkit';
    
    export const postInfo = createAsyncThunk('info/postInfo', async () => {
      throw new Error('get post info fails');
    });
    const postInfoSlice = createSlice({
      name: 'postInfo',
      initialState: {
        request: { status: 'idle', error: '' },
      },
      reducers: {},
      extraReducers: (builder) => {
        builder.addCase(postInfo.rejected, (state, action) => {
          state.request.status = 'failed';
          state.request.error = action.error.message as string;
        });
      },
    });
    
    const store = configureStore({ reducer: postInfoSlice.reducer });
    
    const sendInfoRequest = async () => {
      try {
        await store.dispatch(postInfo()).unwrap();
      } catch (err) {
        console.log('rejected for post /info', err);
      }
    };
    
    sendInfoRequest();
    

    Execution result:

    rejected for post /info {
      name: 'Error',
      message: 'get post info fails',
      stack: 'Error: get post info fails\n' +
        '    at /Users/dulin/workspace/github.com/mrdulin/redux-examples/packages/redux-toolkit-example/stackoverflow/71070359/index.ts:4:9\n' +
        '    at step (/Users/dulin/workspace/github.com/mrdulin/redux-examples/packages/redux-toolkit-example/stackoverflow/71070359/index.ts:33:23)\n' +
        '    at Object.next (/Users/dulin/workspace/github.com/mrdulin/redux-examples/packages/redux-toolkit-example/stackoverflow/71070359/index.ts:14:53)\n' +
        '    at /Users/dulin/workspace/github.com/mrdulin/redux-examples/packages/redux-toolkit-example/stackoverflow/71070359/index.ts:8:71\n' +
        '    at new Promise (<anonymous>)\n' +
        '    at __awaiter (/Users/dulin/workspace/github.com/mrdulin/redux-examples/packages/redux-toolkit-example/stackoverflow/71070359/index.ts:4:12)\n' +
        '    at /Users/dulin/workspace/github.com/mrdulin/redux-examples/packages/redux-toolkit-example/stackoverflow/71070359/index.ts:3:59\n' +
        '    at /Users/dulin/workspace/github.com/mrdulin/redux-examples/packages/redux-toolkit-example/node_modules/@reduxjs/toolkit/dist/redux-toolkit.cjs.development.js:1172:57\n' +
        '    at step (/Users/dulin/workspace/github.com/mrdulin/redux-examples/packages/redux-toolkit-example/node_modules/@reduxjs/toolkit/dist/redux-toolkit.cjs.development.js:38:23)\n' +
        '    at Object.next (/Users/dulin/workspace/github.com/mrdulin/redux-examples/packages/redux-toolkit-example/node_modules/@reduxjs/toolkit/dist/redux-toolkit.cjs.development.js:19:53)'
    }
    

    Or, return a rejected value use thunkAPI.rejectWithValue() instead of throw error in thunk.

    export const postInfo = createAsyncThunk('info/postInfo', async (_, thunkAPI) => {
      // throw new Error('get post info fails');
      return thunkAPI.rejectWithValue({ code: 2000, message: 'parameter invalid' });
    });
    

    Execution result:

    rejected for post /info { code: 2000, message: 'parameter invalid' }