Skip to content

Instantly share code, notes, and snippets.

@Millsky
Last active April 17, 2019 20:38
Show Gist options
  • Save Millsky/d5d79b2468de0e6e50620388889ae98a to your computer and use it in GitHub Desktop.
Save Millsky/d5d79b2468de0e6e50620388889ae98a to your computer and use it in GitHub Desktop.
A functional render pipeline for react
import React, { lazy, Suspense } from "react";
import ReactDOM from "react-dom";
import R from "ramda";
import { task, of } from "folktale/concurrency/task";
function processService(p) {
return p.data;
}
const getDataFailure = data => ({
type: "FAILURE_TYPE",
data: "I failed"
});
const getDataCancelled = data => ({
type: "CANCEL_ME",
data: "I was cancelled"
});
const getDataSuccess = data => ({
type: "SOME_TYPE",
data
});
/* Just a helper function to make our code smaller */
const asChainedTask = R.compose(
// Chain after converting to task
R.chain,
// Curry an unknown number of args
R.o(of)
);
/* Equiv to: /x -> of(x) */
/* R.o - just compresses a lambda via currying */
const asTask = R.o(of);
// F :: _ -> dispatch({t, d})
export const ServicePipeline = R.pipe(
// Generate a new task around a service
() =>
task(resolver => {
// Just resolve to 1 for now
window.setTimeout(() => {
resolver.resolve({ data: 32 });
}, 2000);
}),
// Unwrap the data and send it to process service
// Return a new Task within a chain
// Chain always must expose chain
// so chain passed via any morphism will return chain.
// Equiv to: R.chain(/x => of(fn(x)));
asChainedTask(processService),
// Pick up the data and dispatch an action to redux
// Pattern match for each case
R.chain(data =>
of(data).willMatchWith(
R.map(asTask, {
// Chain will return a chain so only need a task
Cancelled: getDataCancelled,
Resolved: getDataSuccess,
Rejected: getDataFailure
})
)
),
asChainedTask(action => () => <span>Hey {action.data}</span>),
asChainedTask(component => {
return {
default: component
};
})
);
const L = lazy(() =>
ServicePipeline()
.run()
.promise()
);
const LazyC = () => (
<Suspense fallback={<span>Hey...</span>}>
<L />
</Suspense>
);
const root = document.getElementById("root");
ReactDOM.render(<LazyC />, root);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment