Maintain your React state with Cursors.


Maintain your React state with Cursors.

Cursors is a React mixin that is inspired by David Nolen's Om. This is a much lighter implementation that is focused on Nolen's idea of a single global state and using cursors to create smaller local states within a single shared data structure.

Cursors leverages the Immutability Helpers provided by React Add-ons. By avoiding mutation, tasks like undo/redo become trivial, reasoning about problems becomes easier, and bugs are easier to avoid.

bower install cursors

The Cursors object itself should be mixed-in to all Cursors-using components with React's mixin method.

Returns a new cursor with its path set to key's path concatenated with path. key and path should both be a string or number. Use an array of strings and/or numbers for path if your path goes more than one level deep.

Update the state with the change definitions in deltas. For delta syntax check out React's Immutability Helpers.

Check out the test file for a full example. Here's the basics:

var User = React.createClass({
  // First, mixin Cursors to add the appropriate functions to this component 
  // definition. 
  mixins: [Cursors],
  // In order for state changes to be recognized globally, you should never need 
  // to use `this.setState`. Instead, use `this.update`. `update` takes a key 
  // and a delta object. Check the "Immutability Helpers" link for more 
  // information. By using `update`, the value will be updated at the root level 
  // of the cursor, and changes will be propagated down back to the children. 
  // This is a huge win for cursors, because it removes the need to nest 
  // callbacks down for changes to objects that live higher up in the hierarchy. 
  handleChangefunction (ev) {
    this.update({user: {name: {$set:}}});
  // The value of any cursors passed into this component will be reflected in 
  // the `this.state` object. This interface allows children to not depend on 
  // being passed cursors, but use them transparently if they are passed. 
  renderfunction () {
    return <input value={} onChange={this.handleChange} />;
var Users = React.createClass({
  // First, mixin Cursors to add the appropriate functions to this component 
  // definition. 
  mixins: [Cursors],
  // The only component that should need to define `getInitialState` is the root 
  // component. Child components can define their initial state, but state that 
  // is passed into them via parent cursors will override the corresponding 
  // initial state. 
  getInitialStatefunction () {
    return {
      users: this.props.users || []
  // When rendering child components, always pass the appropriate `cursor` for 
  // the child component via `this.getCursor(key, [path])`. 
  renderUserfunction (useri) {
    return <User cursors={{user: this.getCursor('users', i)}} />;
  renderfunction () {
    return <div>{}</div>;
  <MyUsersComponent users={[{name: 'Casey'}, {name: 'Gunner'}]} />,