Skip to content

Instantly share code, notes, and snippets.

@vlas-ilya
Created January 3, 2022 12:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vlas-ilya/6c7554508b031d1b418f700470fd5514 to your computer and use it in GitHub Desktop.
Save vlas-ilya/6c7554508b031d1b418f700470fd5514 to your computer and use it in GitHub Desktop.
Redux | Only one action for async process [no boilerplate code]
import { Init, LoadableData } from "./LoadableData";
import { LoadableDataEvent } from "./LoadableDataEvent";
export function init<T>(data?: T): Init<T> {
return {
state: "init",
data,
};
}
export function updateLoadableData<T>(
previousState: LoadableData<T>,
event: LoadableDataEvent<T>
): LoadableData<T> {
switch (event.state) {
case "isLoading":
return {
state: "isLoading",
data: event.storeDate ? previousState?.data : undefined,
};
case "success":
return {
state: "success",
data: event.data,
};
case "failed":
return {
state: "failed",
data: event.storeDate ? previousState?.data : undefined,
failure: event.failure,
};
}
}
export type Init<T> = {
state: "init";
data?: T;
};
export type IsLoading<T> = {
state: "isLoading";
data?: T;
};
export type Success<T> = {
state: "success";
data: T;
};
export type Failed<T> = {
state: "failed";
data?: T;
failure: Error;
};
export type LoadableData<T> = Init<T> | IsLoading<T> | Success<T> | Failed<T>;
import { FailedEvent, IsLoadingEvent, SuccessEvent } from "./LoadableDataEvent";
export function isLoading<T>(storeDate: boolean = false): IsLoadingEvent<T> {
return {
state: "isLoading",
storeDate,
};
}
export function success<T>(data: T): SuccessEvent<T> {
return {
state: "success",
data,
};
}
export function failed<T>(
failure: Error,
storeDate: boolean = false
): FailedEvent<T> {
return {
state: "failed",
storeDate,
failure,
};
}
export type IsLoadingEvent<T> = {
state: "isLoading";
storeDate: boolean;
};
export type SuccessEvent<T> = {
state: "success";
data: T;
};
export type FailedEvent<T> = {
state: "failed";
storeDate: boolean;
failure: Error;
};
export type LoadableDataEvent<T> =
| IsLoadingEvent<T>
| SuccessEvent<T>
| FailedEvent<T>;
import { LoadableData } from "./LoadableData";
import { init, updateLoadableData } from "./LoadableData.helpers";
import { LoadableDataEvent } from "./LoadableDataEvent";
import { failed, isLoading, success } from "./LoadableDataEvent.helpers";
/// App
type UpdateStateAction = {
type: "UPDATE_STATE";
payload: LoadableDataEvent<String[]>;
};
type State = {
list: LoadableData<String[]>;
};
const state = {
list: init<String[]>(),
} as State;
const updateStateAction = (payload: LoadableDataEvent<String[]>): UpdateStateAction => ({
type: "UPDATE_STATE",
payload,
});
const reducer = (state: State, action: UpdateStateAction): State => {
switch (action.type) {
case "UPDATE_STATE":
return {
...state,
list: updateLoadableData(state.list, action.payload),
};
default:
return state;
}
};
/// Tests
console.log(state);
const isLoadingState = reducer(state, updateStateAction(isLoading()));
console.log(isLoadingState);
const failedState = reducer(state, updateStateAction(failed(Error("error"))));
console.log(failedState);
const successState = reducer(state, updateStateAction(success(["Message"])));
console.log(successState);
const isLoadingStateWithData = reducer(
successState,
updateStateAction(isLoading(true))
);
console.log(isLoadingStateWithData);
const failedStateWithData = reducer(
successState,
updateStateAction(failed(Error("error"), true))
);
console.log(failedStateWithData);
const successNewState = reducer(
successState,
updateStateAction(success(["Message2"]))
);
console.log(successNewState);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment