Search code examples
javascriptreactjsreduxreact-reduxredux-thunk

How to handle promise from an Action from React Redux


export const uploadFile = createAsyncThunk(
  "simulation/uploadFile",
  async (filesSelected) => {
    console.log(filesSelected[0].name + " Will be uploaded");

    const formData = new FormData();

    formData.append(filesSelected.name, filesSelected);
    formData.append("dcmFile", filesSelected[0]);
    formData.append("mdfFile", filesSelected[1]);
    formData.append("modelFile", filesSelected[2]);

    const response = await axios
      .post("http://localhost:8000/simulation/start/", formData)
      .then((response) => {
        /**
         * The 'then' method is executed only when the request is successfull.
         */
        console.log(response);
      })
      .catch((err) => {
        /**
         *  The 'catch' method is executed only when the request fails to complete.
         */
        console.log(err);
      });
    console.log(response.statusText);
    return response.statusText;
  }
);
dispatch(uploadFile);

I want to wait for this dispatch to dispatch if axios return an error I want to pop a message to the user if everything goes smoothly I also want to display a message.


Solution

  • I think the best practice with handling createAsyncThunk errors is to handle it in the slice. So instead of catching the error in your createAsyncThunk action, let the error happen, and then in the slice, it should look like so:

    const initialState = {
        getStatus: {},
        doStatus: {},
    };
    
    export const mockSlice = createSlice({
        name: 'mock',
        initialState,
        reducers: {
            resetDoStatus: (state) => {
                state.doStatus = {};
            },
        },
        extraReducers: (builder) => {
            builder
                .addCase(uploadFile.pending, (state) => {
                    state.doStatus.pending = true;
                })
                .addCase(uploadFile.rejected, (state, action) => {
                    state.doStatus.pending = false;
                    state.doStatus.errorMessage = action.error.message;
                    state.doStatus.error = true;
                })
                .addCase(
                    uploadFile.fulfilled,
                    (state) => {
                        state.doStatus.pending = false;
                        state.doStatus.success = true;
                        state.doStatus.successMessage = "Upload success!"
                    }
                );
        },
    });
    
    export const {
        resetDoStatus: resetMockDoStatus,
    } = mockSlice.actions;
    export const mockSlice = mockSlice.reducer;
    

    By doing it like so, you can simply get the error in your component and display the error however you like, you can also have loading components according to your state and reset it all however you like.