JSFiddle - React, Tailwind, and code Playground
HTML
<script src="http://fb.me/react-with-addons-0.9.0.js"></script>
<script src="http://fb.me/JSXTransformer-0.9.0.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore.js"></script>
<script src="http://fb.me/react-js-fiddle-integration.js"></script>
JavaScript 1.7
/** @jsx React.DOM */
var App = React.createClass({
getInitialState: function() {
return {
count: 0
};
},
render: function() {
var cursor = Cursor.build(this.state, this.setState.bind(this), cloneDeep);
return this.transferPropsTo( < Clicker cursor = {
cursor
}
/>);
}
});
var Clicker = React.createClass({
render: function() {
return ( <
div >
<
span > {
this.props.cursor.refine('count').value
} < /span> <
button onClick = {
this.inc2
} > +2 < /button> < /
div >
);
},
inc2: function() {
var countCursor = this.props.cursor.refine('count');
countCursor = countCursor.onChange(countCursor.value + 1);
countCursor = countCursor.onChange(countCursor.value + 1);
}
});
// this constructor is private
function Cursor(state, path, commit, clone) {
state = clone(state); // defensive clone right away so we can't close over a stale state reference
this.value = getRefAtPath(state, path);
this.onChange = function(nextValue) {
var nextState;
nextValue = clone(nextValue); // because the call site might retain the reference and mutate
if (path.length > 0) {
nextState = state;
var scoped = getRefAtPath(nextState, initial(path));
scoped[last(path)] = nextValue;
} else if (path.length === 0) {
nextState = nextValue;
}
commit(nextState);
return new Cursor(nextState, path, commit, clone);
};
this.refine = function( /* one or more paths through the tree */ ) {
var nextPath = [].concat(path, flatten(arguments));
return new Cursor(state, nextPath, commit, clone);
};
}
/**
* Example usages:
* Cursor.build(this.state,...