Damien Teo
Damien Teo

Reputation: 21

createAsyncThunk: error upon calling endpoint is not triggering .rejected

I am trying out '@reduxjs/toolkit' v1.4.0

I have been trying out error handling. Although I can get the error from the endpoint:

{
  "code": "missing_access_key",
  "message": "You have not supplied an API Access Key. [Required format: access_key=YOUR_ACCESS_KEY]"
}

I am unable to get it to trigger:

    builder.addCase(fetchUsers.rejected, (state, action) => {
      // FIXME: rejected not being called on error
      state.loading = false
      state.error = action.error.message
    })

I keep looking at the docs and have even tried rejectWithValue. The 'pending' and 'fulfilled' conditions are called upon success, but I can't seem to trigger 'rejected'. I have tried try/catch blocks as well. Would be very grateful if anyone can let me know what I am doing wrong.

export const fetchUsers = createAsyncThunk(
  'posts/fetchUsers',
  async (users: Users) => {
    const response: any = await fetch(
      `${ENDPOINTS.USERS_SOURCE}tickers/search=${answers.ticker}&access_key=${process.env.MARKET_WATCH_API_KEY}&limit=${RESULTS_LIMIT}`
    )

    return response.data
  }
)

type SliceState = {
  error?: null | string
  loading: boolean
  data: null | SingleUser
  selectedData: null | SingleUser
}

// First approach: define the initial state using that type
const initialState: SliceState = {
  error: null,
  loading: false,
  data: null,
}

export const UsersSlice = createSlice({
  name: 'Users',
  initialState,
  reducers: {
    clearUsers: (state) => {
      state.data = null
    },
  },
  extraReducers: (builder) => {
    builder.addCase(fetchUsers.pending, (state) => {
      state.data = null
      state.loading = true
    })
    builder.addCase(fetchUsers.fulfilled, (state, action) => {
      state.loading = false
      state.data = action.payload
    })
    builder.addCase(fetchUsers.rejected, (state, action) => {
      // FIXME: rejected not being called on error
      state.loading = false
      state.error = action.error.message
    })
  },
})

export const { clearUsers } = UsersSlice.actions

export default UsersSlice.reducer

Upvotes: 2

Views: 1096

Answers (1)

Max Smolens
Max Smolens

Reputation: 3811

The fetch() method returns a Promise that resolves regardless of whether the request is successful, unless there's a network error. In other words, the Promise isn't rejected even when the response has an HTTP 400 or 500 status code.

To ensure the fetchUsers.rejected reducer is called in this case, you should check Response.ok after the Promise resolves as in this minimal example:

const response = await fetch(url)

if (!response.ok) {
  // throw appropriate error
}

...

See Using Fetch for more information.

Upvotes: 2

Related Questions