Last active
August 29, 2015 14:16
-
-
Save seanhess/e7322726b9a39c6fecf9 to your computer and use it in GitHub Desktop.
Cursor Proposal
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
const React = window.React = require('react') | |
const {map, append, partial, curry, compose} = require('ramda') | |
const shortid = require('shortid') | |
// STATE -------------------------------------------------------- | |
// returns a state object, and automatically creates sub-cursors | |
// state.items = cursor to items | |
// state.items[0] = cursor to items[0]. | |
const state = magicCursorFunction({ | |
items: [ | |
{id: 1, name: "one"}, | |
{id: 2, name: "two"}, | |
{id: 3, name: "three"}], | |
}) | |
// API: CURSOR | |
// cursor.get() | |
// cursor.update(f) | |
// cursor.set(v) | |
// cursor.x = child cursor | |
// VIEW ----------------------------------------------------------- | |
// each component gets passed a cursor that points to some js data | |
// call .get() to get the data, or .set() or .update() to trigger an update | |
const TodoItem = React.createClass({ | |
render() { | |
const cursor = this.props.cursor | |
const item = cursor.get() | |
// note you can do cursor.name.get() instead of cursor.get().name | |
function onChange(e) { | |
cursor.update(setName(e.target.value)) | |
// also works: | |
// cursor.name.set(e.target.value) | |
} | |
// other ways of writing the same thing | |
// I'm not sure it's helpful to create change functions like this | |
// it's probably always clearer to define a callback above | |
// maybe: cursor.makeUpdate() | |
const onChange2 = compose(cursor.update, setName, eventValue) | |
return <li> | |
<input value={item.name} onChange={onChange}/> | |
</li> | |
} | |
}) | |
const TodoList = React.createClass({ | |
render() { | |
const itemsCursor = this.props.cursor | |
const renderItem = i => <TodoItem cursor={i} key={i.id}/> | |
return <ul> | |
{map(renderItem, itemsCursor)} | |
</ul> | |
} | |
}) | |
const TodoApp = React.createClass({ | |
render() { | |
const cursor = this.props.cursor | |
const onAdd = () => cursor.update(addEmptyItem) | |
return <div className="row small-12 columns"> | |
<h1>Items</h1> | |
<button onClick={onAdd}>Add Item</button> | |
<TodoList cursor={cursor} /> | |
</div> | |
} | |
}) | |
// I want to add items easily | |
const App = React.createClass({ | |
render() { | |
return <TodoApp cursor={state.items}/> } | |
}) | |
function render() { | |
React.render( | |
<App/>, | |
document.getElementById('content') | |
) | |
} | |
render() | |
state.onUpdate(render) | |
// HELPERS -------------------------------------------------------- | |
// notice that none of these deal with cursors. They're all functions | |
// that just deal with data, and are immutable-style | |
const addItem = curry(function(item, items) { | |
return append(item, items) | |
}) | |
const emptyItem = function() { | |
return {id: shortid.generate(), name: ""} | |
} | |
const addEmptyItem = compose(addItem, emptyItem) | |
const setName = curry(function(value, item) { | |
item.name = value | |
return item | |
}) | |
const eventValue = function(e) { | |
return e.target.value | |
} | |
@murphyrandle yep, great! It's kept up to date the same way as omniscient, the component should get refreshed every time it's updated. I haven't implemented anything yet, so I don't have details, but the basic idea is that a cursor is just an addressing function into the data and a reference to the current data.
Okay cool. As far as the api goes I think it looks good. @numso and I worked out a potential alternative last night as well, and he implemented a test today. I'd like for him to post that up so that we can all comment on it also.
Btw, I decided not to vet the idea I brought up earlier about pouchdb. I don't really want us to do that. :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
So this is a strawman of what the api will look like? I like it. How do you keep the cursor up to date? does the state update its items attribute to be a refreshed cursor whenever the underlying structure is changed?