Skip to content

Instantly share code, notes, and snippets.

@geophree
Last active August 22, 2016 18:08
Show Gist options
  • Save geophree/522942ae19bd105743a35cff48feab28 to your computer and use it in GitHub Desktop.
Save geophree/522942ae19bd105743a35cff48feab28 to your computer and use it in GitHub Desktop.
Universal redux-saga server-side render
import R from 'ramda';
import ReactDOMServer from 'react-dom/server';
import { put, call } from 'redux-saga/effects';
const LOADING = 'LOADING';
const MAX_RENDERS = 10;
export function renderUntilDone(store, app) {
return new Promise((resolve, reject) => {
let again = true;
let renderCount = 0;
let html;
const unsub = store.subscribe(onChange);
onChange(true);
function onChange(first = false) {
const loading = store.getState().loading;
if (!first && loading && loading.length) {
again = true;
return;
}
if (again) {
again = false;
render();
}
// This may not work if onChange isn't called sync during render
if (!again) {
unsub();
resolve(html);
}
}
function render() {
renderCount++;
if (renderCount > MAX_RENDERS) {
unsub();
return reject(new Error(`Tried to render more than ${MAX_RENDERS} times.`));
}
const state = store.getState();
html = ReactDOMServer.renderToString(app(state));
}
});
}
export function reducer(state = [], action) {
if (action.type !== LOADING) return state;
// no-dupes version
// const mod = action.finished ? R.without([action.data]) : R.compose(R.uniq, R.append(action.data));
const without = R.without([action.data]);
const oneLess = R.compose(R.tail, R.filter(R.equals(action.data)));
const removeOne = R.converge(R.concat, [without, oneLess]);
const mod = action.finished ? removeOne : R.append(action.data);
return mod(loading);
}
// Wrap your loading sagas with this function
export function *addLoading(type, func, ...args) {
const data = [type, func, ...args];
yield put({ type: LOADING, data });
try {
yield call(func, ...args);
} finally {
yield put({ type: LOADING, data, finished: true });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment