最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Question about error handling in redux toolkit (rejected, fulfilled) - Stack Overflow

programmeradmin5浏览0评论

I'm getting into using redux-toolkit and after reading the docs and implementing some code, there's something I don't quite understand, or maybe my approach is wrong, thats why I'm asking here.

Anyways, I'm having some slice with some asyncThunk which makes a call to an API and sets some state from values returned from that call, and if it fails, show an error notification and some logging. I'm not at work at the moment so I'll write some pseudo code:

const loadData = createAsyncThunk('loadData',
    async ({ product }, { dispatch, extra: { API }, rejectWithValue }) => {
        try {
            const response = await API.getProduct(product)
            return response
        } catch (error) {
            dispatch(setErrorNotification(error.message))
            dispatch(logError(error))
            rejectWithValue(null)
        }
    }

This code does what I want actually, but my question lies in having to use rejectWithValue(null)for the code to go through the rejected reducer, , which looks really fishy to me and it makes me believe I'm not understanding this quite well. If I don't do this, even if it goes into the catch, it goes through the fulfilled reducer which throws an error since this is not expected and there's no payload.

Any pointers? is there a way for, when catching the API call (in case of failure) going to the rejected reducer without having to explicitly rejectWithValue?

Thanks!

I'm getting into using redux-toolkit and after reading the docs and implementing some code, there's something I don't quite understand, or maybe my approach is wrong, thats why I'm asking here.

Anyways, I'm having some slice with some asyncThunk which makes a call to an API and sets some state from values returned from that call, and if it fails, show an error notification and some logging. I'm not at work at the moment so I'll write some pseudo code:

const loadData = createAsyncThunk('loadData',
    async ({ product }, { dispatch, extra: { API }, rejectWithValue }) => {
        try {
            const response = await API.getProduct(product)
            return response
        } catch (error) {
            dispatch(setErrorNotification(error.message))
            dispatch(logError(error))
            rejectWithValue(null)
        }
    }

This code does what I want actually, but my question lies in having to use rejectWithValue(null)for the code to go through the rejected reducer, , which looks really fishy to me and it makes me believe I'm not understanding this quite well. If I don't do this, even if it goes into the catch, it goes through the fulfilled reducer which throws an error since this is not expected and there's no payload.

Any pointers? is there a way for, when catching the API call (in case of failure) going to the rejected reducer without having to explicitly rejectWithValue?

Thanks!

Share Improve this question asked Mar 10, 2021 at 18:42 milanesamilanesa 332 silver badges6 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

It is not fishy at all. It is the way to put all burden of changing state to reducers in convenient way. Let's look at code like this: let promise = promiseReturningFunction();. Here we have some generic promise and now we can "subscribe" on future value of it with then and catch. We also can subscribe to future values multiple times, like this:


let promise = promiseReturningFunction();
promise.then(doSomething);
promise.then(doSomethingElse);

Redux toolkit preserves this pattern. Thunks are detached from specific slices and you can "subscribe" to them in multiple reducers. So when you want to do multiple things in different slices on same result, you will get raw data from thunk and in different slices process that data as you need in particular case.

In your case, you should call return rejectWithValue(error). Then, in slice that is responsible for errors you add this:

extraReducers: {
  [loadData.rejected]: (state, action) => {
    // do something with error that is in action.payload
  }
}

This is good pattern in case when you handle errors in one slice, but might need to know that it settled in another. It is also future proof in two ways: you always can add slice that use same thunk, and you always can replace thunk pletely without breaking things (if shapes of data don't change).

Update

Example sandbox: https://codesandbox.io/s/fancy-cdn-d86c9?file=/src/App.js

发布评论

评论列表(0)

  1. 暂无评论