React-cursor: a JavaScript implementation of the Cursor concept first seen in Om
github.com
github.com
> It might be best to think of setState as being enqueueStateUpdate
Is this why the cursor objects have something like a "pendingState" property? I can't remember the exact name, just that it exists.
`cursor.pendingValue()` gives you the latest queued state update, which is always what you want in your event handlers (e.g. complicated state transitions in response to a click).
The decision is essential complexity, but at least when you use cursors the decision is mechanical. React has a slightly different API (but equivalent information) that makes the decision less mechanical.
Cortex's goal is to support arbitrarily deep data structure without requiring you to pass callbacks down the chain.
I'd love some input from users of om or one of the pure js solutions how it works for them. For example, how would one go about monitoring state outside of a component? Think submitting analytics events when a user does something.
Mozilla's localForage is a good tool specifically for abstracting away the client-side storage mechanism from the UI logic. Aside from that I have looked at Flux and its stores would be the place where you would implement such a facade.
It's interesting to imagine what the lighter facade you're describing might look like. I guess you'd want the controllers/views to get a key-value style interface, and you'd want the facade to connect with one or more local storage options, and some sort of logic to manage triage between local and remote storage, and syncing between the two, and a well-defined API for connecting the remote storage. Hmmm...
One thing I'm a little confused about is the onChange method. Is that supposed to be like Om's transact? If so, that seems like an unfortunate name. onChange sounds like a callback, not a way to create a new state.
For example
cursor.refine('b').refine('foo').onChange({ 'bar': 43, baz: 56 })
What is this doing? If onChange isn't transact, what is the react-cursor equivalent?
onChange: function(e) { this.cursor.onChange(e.value);}
Even in that case, I think it is a lot more intuitive to use a function name like `change`, `mutate`, or `transact`. Personally, `onChange` is something I want to assign, not something I want to call. Additionally, it doesn't look like it can be passed a raw Event object, so you can't shorthand it in a render method and avoid creating an onChange callback.I would prefer `transact` or any other of your proposed method names over onChange.
I ended up hacking my own version of the same idea, but with an explicit reference to a mutable data slot, much like the cursors in this post do.
I use a lot of Immutable.Record for domain objects, and I found that I could get nicely succinct code by adding a getter property to the cursor for each field in a record. It yields a new cursor if the value is an immutable collection too, or else the actual value the cursor points to. This seems like a weird heuristic until you realize that most programming languages make the same distinction (primitive values are cloned, object references are not).
This allows me to write code like
<span>{this.props.user.group.name}</span>
Where this.props.user is a cursor, not an immutable collection. This is cool, because I only pass around subcursors around my component tree, but I can address them as if they're the values themselves when rendering. And I can still mutate them as a cursor.I didn't publish this code, or even evaluate the performance of it, but if anyone cares I don't mind sharing.
I'm curious whether you could shoot any holes in that reasoning.
http://swannodette.github.io/2013/12/17/the-future-of-javasc...
I've looked into Om/ClojureScript now a few times and the learning curve is steep and keeps putting me off, but also I fear that if I start a project with it I'll alienate potential future devs and have difficulty gaining traction. Plus, with ES6/CoffeeScript/TypeScript and libraries like this it's more possible than ever to build a beautiful environment to code in that doesn't require such a big jump.
But hey, at least this stuff brings more exposure to ClojureScript. That's definitely a good sign.
In my experience, I joined a company specifically to learn/use clojurescript and others joined the same time, and we were committing code after 2 weeks.
Om has a steep learning curve. I'd recommend quiescent if you want the bare minimum for interfacing with React in cljs.
cursor.refine('foo', 3).onChange('d')
cursor.refine('foo').onChange(['a', 'b', 'c', 'd'])
(indexes in a js array are the same as keys in a map)It is possible to implement `push` and other list/object ops that are exposed by React.addons.update, they have not been implemented yet because they make the interface more complicated.
http://facebook.github.io/react/docs/update.html
I opened an issue for discussion: https://github.com/dustingetz/react-cursor/issues/10
cursor.refine('foo').onChange({'child':{}});
in one place and then in some other, code that would dwelve inside that child recursively (and append the "add child" action to that node as well)My goal is to have a json editor with json as the only model in the application and have react/cursor automatically render the tree, and allow its modification (removing and adding nodes).
Such functionality would require cursor to "dive" inside a json node without knowing its name - I'm not sure whether the 'push' op you are mentioning would be required to achieve this.