Created
January 4, 2024 16:21
-
-
Save nilscox/70a0c8f0d87c24e845ae6d90d4a7587f to your computer and use it in GitHub Desktop.
Redux slice to track the lifecycles of redux toolkit's async thunks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
SerializedError, | |
createSelector, | |
createSlice, | |
isAsyncThunkAction, | |
isFulfilled, | |
isPending, | |
isRejected, | |
} from '@reduxjs/toolkit'; | |
// import from somewhere | |
type AppState = {}; | |
type AsyncThunkLifecycleStatePending = { | |
status: 'pending'; | |
}; | |
type AsyncThunkLifecycleStateFulfilled = { | |
status: 'fulfilled'; | |
result: unknown; | |
}; | |
type AsyncThunkLifecycleStateRejected = { | |
status: 'rejected'; | |
error: SerializedError; | |
}; | |
type AsyncThunkLifecycleState = | |
| AsyncThunkLifecycleStatePending | |
| AsyncThunkLifecycleStateFulfilled | |
| AsyncThunkLifecycleStateRejected; | |
type AsyncThunkLifecycleSlice = Record<string, AsyncThunkLifecycleState>; | |
export const asyncThunkLifecycleSlice = createSlice({ | |
name: 'asyncThunkLifecycle', | |
initialState: {} as AsyncThunkLifecycleSlice, | |
reducers: {}, | |
extraReducers(builder) { | |
builder.addMatcher(isAsyncThunkAction, (state, action) => { | |
const { requestId } = action.meta; | |
if (isPending(action)) { | |
state[requestId] = { | |
status: 'pending', | |
}; | |
} | |
if (isFulfilled(action)) { | |
state[requestId] = { | |
status: 'fulfilled', | |
result: action.payload, | |
}; | |
} | |
if (isRejected(action)) { | |
state[requestId] = { | |
status: 'rejected', | |
error: action.error, | |
}; | |
} | |
}); | |
}, | |
}); | |
const selectSlice = (state: AppState) => { | |
return state[asyncThunkLifecycleSlice.reducerPath]; | |
}; | |
const selectAsyncThunkState = createSelector( | |
selectSlice, | |
(state: AppState, requestId: string | undefined) => requestId, | |
(slice, requestId) => { | |
if (requestId) { | |
return slice?.[requestId]; | |
} | |
}, | |
); | |
export const selectAsyncThunkStatus = createSelector(selectAsyncThunkState, (state) => { | |
return state?.status; | |
}); | |
export const selectAsyncThunkError = createSelector(selectAsyncThunkState, (state) => { | |
if (state?.status === 'rejected') { | |
return state?.error; | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment