Skip to content

Instantly share code, notes, and snippets.

View zzdjk6's full-sized avatar

Thor(Shenghan) Chen zzdjk6

  • Palmerston North, New Zealand
View GitHub Profile
// When abort happens, this error will be throw
class AbortError extends Error {
constructor(message: string = 'Aborted') {
super(message);
this.name = 'AbortError';
}
}
// General interface of Abortable
interface Abortable {
// Imagine we defined a thunk action creator from routine
const fetchData = getThunkActionCreator(fetchDataRoutine, async (id: number) => {
return await api.fetchData(id);
});
// We could write another thunk action creator to access the existing state
const fetchDataWithIdFromState = () => (dispatch: Dispatch, getState: () => RootState) => {
const id = getState().somewhere.id;
return dispatch(fetchData(id));
};
// Use type guards
const reducer = (state: State = initState, action: Action<any>): State => {
// isSuccessAction is a type guard
if (fetchDataRoutine.isSuccessAction(action)) {
// action is typed as Action<DataType>, so payload is DataType
const payload = action.payload;
// ...
}
// isFailureAction is a type guard
type ValidAction =
| ReturnType<typeof fetchDataRoutine.request>
| ReturnType<typeof fetchDataRoutine.success>
| ReturnType<typeof fetchDataRoutine.failure>;
const reducer = (state: State = initState, action: ValidAction): State => {
// The reducer logic goes here...
};
const reducer = (state: State = initState, action: Action<any>): State => {
// The reducer logic goes here...
};
const fetchData = getThunkActionCreator(
fetchDataRoutine,
async (id: number) => {
return await api.fetchData(id);
},
{
// this is optional
getRequestPayload: async (id: number) => {
return {
overwrittenPayload: id
const fetchData = getThunkActionCreator(fetchDataRoutine, async (id: number) => {
return await api.fetchData(id);
});
// 1. Define a routine
const fetchDataRoutine = createThunkRoutine<DataType>('FETCH_DATA');
// Or explicitly decalre the error type if need
// const fetchDataRoutine: createThunkRoutine<DataType, Error>('FETCH_DATA')
// 2. Define the thunk action creator
// Note: We will address the repetitive logic flow later on
const fetchData = (id: number) => async (dispatch: Dispatch) => {
await dispatch(fetchDataRoutine.request(id));
try {
// 1. Define the constants that are used as action types
const FETCH_DATA_REQUEST = 'FETCH_DATA/REQUEST';
const FETCH_DATA_SUCCESS = 'FETCH_DATA/SUCCESS';
const FETCH_DATA_FAILURE = 'FETCH_DATA/FAILURE';
// 2. Define synchronous action creators (following Flux Standard Action)
const fetchDataRequest = (payload?: any) => {
if (typeof payload === 'undefined') {
return {
type: FETCH_DATA_REQUEST
// To know more about ducks, see https://github.com/erikras/ducks-modular-redux
import { Action } from 'redux-actions';
import { RootState } from '../../store';
import { createSelector } from 'reselect';
// State
// To know more about Record type, see https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkt
export type ErrorState = Record<string, Error | null>;