All Projects → jcoreio → meteor-immutable-observer

jcoreio / meteor-immutable-observer

Licence: other
Autoupdating Immutable.js views of Meteor live queries (useful for React pure render components!)

Programming Languages

javascript
184084 projects - #8 most used programming language
shell
77523 projects
HTML
75241 projects

meteor-immutable-observer

(work in progress!)

This uses Mongo.Cursor.observe and Mongo.Cursor.observeChanges to provide Immutable.js views of the collection and its documents. This is especially handy to pass to React pure render components; when documents are changed, a custom updateDeep method is used so that objects/arrays inside them that didn't change will still be === their previous values.

Installation

Node/Webpack/Browserify/jspm/HTML9 Responsive Boilerstrap JS

npm install meteor-immutable-observer

Then var ImmutableObserver = require('meteor-immutable-observer')

There are Webpack UMDs in the lib/umd folder (they rely on immutable being in a commons chunk)

Meteor Package (not deployed here yet)

meteor add mindfront:immutable-observer

This will put ImmutableObserver in the package scope.

API

Note: this doesn't seem to work properly when you Meteor.subscribe() to your collection within the same reactive computation. I haven't yet investigated exactly why. Right now I just subscribe() outside of any reactive computation.

ImmutableObserver.Map(cursor: Mongo.Cursor)

Begins a live query via cursor.observeChanges, and tracks changes in an Immutable.Map of documents indexed by _id.

Theoretically this should perform better than ImmutableObserver.List, since it doesn't keep track of document order.

This should not be called within a reactive computation. Since its observeChanges can trigger dependency changes, it could cause an infinite autorun loop.

Make sure you stop() the observer when done with it.

Example:
var Players = new Meteor.Collection('players');
var observer = ImmutableObserver.Map(Players.find({}, {limit: 10}));
...
observer.stop();

Methods

documents(): Immutable.Map

Returns an Immutable.Map of the currently available documents, indexed by _id.

Also registers a dependency on the underlying live query.

stop()

Stops the live query (calls stop() on what observeChanges returned)

ImmutableObserver.List(cursor: Mongo.Cursor)

Begins a live query via cursor.observe, and tracks changes in an Immutable.List of documents in order.

This should not be called within a reactive computation. Since its observe can trigger dependency changes, it could cause an infinite autorun loop.

Make sure you stop() the observer when done with it.

Example:
var Players = new Meteor.Collection('players');
var observer = ImmutableObserver.List(Players.find({}, {sort: {score: 1}, limit: 10}));
...
observer.stop();

Methods

documents(): Immutable.List

Returns an Immutable.List of the currently available documents.

Also registers a dependency on the underlying live query.

stop()

Stops the live query (calls stop() on what observe returned)

Example (not tested)

import React from 'react';
import classNames from 'classnames';
import ImmutableObserver from 'meteor-immutable-observer';
import shouldPureComponentUpdate from 'react-pure-render/function';

class Post extends React.Component {
  shouldComponentUpdate = shouldPureComponentUpdate
  render() {
    var {post} = this.props;
    return <div className="panel">
      <div className="panel-heading">
        <h3 className="panel-title">{post.get('title')}</h3>
        <button><i className={post.get('isLiked') ? "glyphicon glyphicon-heart" : "glyphicon glyphicon-heart-empty"}/></button>
      </div>
      <div className="panel-body">
        {post.get('content')}
      </div>
    </div>;
  }  
}

class PostList extends React.Component {
  shouldComponentUpdate = shouldPureComponentUpdate
  render() {
    var {posts} = this.props;
    var postComponents = [];
    posts.forEach(post => postComponents.push(<Post post={post}/>));
    return <div className="posts">
      {postComponents}
    </div>;
  }
}

export default React.createClass({
  mixins: [ReactMeteorData], 
  componentWillMount() {
    this.subscription = Meteor.subscribe('posts');
    this.postsObserver = ImmutableObserver.List(Posts.find({}, {sort: {createdDate: 1}}));
  }
  componentWillUnmount() {
    this.subscription.stop();
    this.postsObserver.stop();
  }
  getMeteorData() {
    return {
      posts: postsObserver.documents(),
    };
  },
  render() {
    return <PostList {...this.props} {...this.data}/>;
  }
});
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].