Last active
February 21, 2017 23:50
-
-
Save mikaelbr/9dfac0137f5baf294863 to your computer and use it in GitHub Desktop.
Example of functional UI and higher order components for React/Omniscient.js (http://omniscientjs.github.io/)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import component from 'omniscient'; | |
import immstruct from 'immstruct'; | |
import { compose, valueNode, partialProps } from './compose'; | |
const data = immstruct({ counter: 0, title: 'My title' }); | |
const em = component(({partialedTitle, children}) => | |
<em>{partialedTitle}: {children}</em>); | |
const h1 = component(({titleCursor, children}) => | |
<h1 className="heading--someModifier">{titleCursor.valueOf()}: {children}</h1>); | |
const partialedEm = partialProps(em, { | |
partialedTitle: 'My partialed property' | |
}); | |
const ComposedComponent = compose(h1, partialedEm, valueNode(props => props.counter)); | |
const App = component(function (props) { | |
return <div> | |
<h1>Composed on valueNode</h1> | |
{ComposedComponent(props)} | |
</div> | |
}); | |
const render = () => | |
React.render( | |
App({ | |
counter: data.cursor('counter'), | |
titleCursor: data.cursor('title') | |
}), | |
document.body); | |
/* or simply: | |
const render = () => | |
React.render( | |
ComposedComponent({ | |
counter: data.cursor('counter'), | |
titleCursor: data.cursor('title') | |
}), | |
document.body); | |
*/ | |
render(); | |
data.on('swap', render); | |
setInterval( | |
() => data.cursor().update('counter', i => i + 1), | |
1000); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import assign from 'lodash.assign'; | |
export function compose (...fns) { | |
return (...args) => | |
fns.reduceRight((child, fn) => | |
fn.apply(this, child ? args.concat(child) : args), null); | |
}; | |
// For just using single value nodes in React. | |
export function valueNode (pick) { | |
return props => <span>{pick(props).valueOf()}</span>; | |
}; | |
//-- Partial Applications | |
export function partialProps (fn, partialInput) { | |
return function partialedProps (key, props, statics) { | |
// Same default args code as Omniscient Core | |
let _props; | |
if (typeof key === 'object') { | |
statics = props; | |
props = key; | |
key = void 0; | |
} | |
if (isCursor(props) || isImmutable(props)) { | |
_props = props; | |
} else { | |
_props = assign({}, props, partialInput); | |
} | |
const children = flatten(sliceFrom(arguments, statics).filter(isNode)); | |
if (isNode(statics)) { | |
statics = void 0; | |
} | |
return fn.apply(this, [key, _props, statics].concat(children)); | |
}; | |
} | |
// * Helpers for partial implementation. Functions from Omniscient core | |
function toArray (args) { | |
return [].slice.apply(args); | |
} | |
function isCursor (potential) { | |
return !!(potential && typeof potential.deref === 'function'); | |
} | |
var IS_ITERABLE_SENTINEL = '@@__IMMUTABLE_ITERABLE__@@'; | |
function isImmutable(maybeImmutable) { | |
return !!(maybeImmutable && maybeImmutable[IS_ITERABLE_SENTINEL]); | |
} | |
function flatten (array) { | |
return Array.prototype.concat.apply([], array); | |
} | |
function sliceFrom (args, value) { | |
var array = toArray(args); | |
var index = Math.max(array.indexOf(value), 0); | |
return array.slice(index); | |
} | |
function isNode (propValue) { | |
switch (typeof propValue) { | |
case 'number': | |
case 'string': | |
return true; | |
case 'boolean': | |
return !propValue; | |
case 'object': | |
if (Array.isArray(propValue)) { | |
return propValue.every(isNode); | |
} | |
if (React.isValidElement(propValue)) { | |
return true; | |
} | |
return false; | |
default: | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment