Skip to content

Instantly share code, notes, and snippets.

@nilscox
Created January 4, 2024 16:21
Show Gist options
  • Save nilscox/70a0c8f0d87c24e845ae6d90d4a7587f to your computer and use it in GitHub Desktop.
Save nilscox/70a0c8f0d87c24e845ae6d90d4a7587f to your computer and use it in GitHub Desktop.
Redux slice to track the lifecycles of redux toolkit's async thunks
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