Skip to content

Instantly share code, notes, and snippets.

@dufia
Created February 16, 2020 17:02
Show Gist options
  • Save dufia/09d76a2cdfe1e0abeae934a8dfd7dd29 to your computer and use it in GitHub Desktop.
Save dufia/09d76a2cdfe1e0abeae934a8dfd7dd29 to your computer and use it in GitHub Desktop.
Toaster saga
import { HIDE_TOAST, SHOW_TOAST, updateToasts } from '../actions';
import { all, delay, fork, put, take, takeEvery } from 'redux-saga/effects';
function* toasterSaga() {
const MaxToasts = 3;
const ToastDisplayTime = 5000;
const ToastAnimationTime = 500;
const toastTimers: number[] = []; // keep track of when toasts are added
const pendingToasts: any[] = [];
let activeToasts: any[] = [];
function* displayToast(toast) {
// get the latest timer
const latestTimer = toastTimers.pop() || Date.now();
// create a latest timer from previous latest timer and add 300ms
toastTimers.push(latestTimer + 300);
// wait enough time so there is a delay between two slides showing
yield delay(latestTimer - Date.now());
activeToasts.push(toast);
yield put(updateToasts([...activeToasts]));
yield delay(ToastDisplayTime);
toast.open = false;
yield put(updateToasts([...activeToasts]));
yield delay(ToastAnimationTime);
activeToasts = activeToasts.filter(t => t.id !== toast.id);
yield put(updateToasts([...activeToasts]));
yield fork(toastScheduler);
}
function* toastWatcher() {
while (true) {
const { payload: toast } = yield take(SHOW_TOAST);
pendingToasts.push(toast);
yield fork(toastScheduler);
}
}
yield takeEvery(HIDE_TOAST, removeToast);
function* removeToast(action) {
const toast = activeToasts.find(t => t.id === action.payload);
if (toast) {
toast.open = false;
yield put(updateToasts([...activeToasts]));
yield delay(ToastAnimationTime);
activeToasts = activeToasts.filter(t => t.id !== toast.id);
yield put(updateToasts([...activeToasts]));
yield fork(toastScheduler);
}
}
function* toastScheduler() {
const canDisplayToast = activeToasts.length < MaxToasts && pendingToasts.length > 0;
if (canDisplayToast) {
const toast = pendingToasts.shift();
yield fork(displayToast, toast);
}
}
yield toastWatcher();
}
export default function* rootSaga() {
yield all([toasterSaga()]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment