All Projects → Q42 → autovars

Q42 / autovars

Licence: MIT License
Reactive state management for Meteor + React

Programming Languages

javascript
184084 projects - #8 most used programming language

AutoVars

Reactive state management for Meteor + React

Why should I use this?

Meteor and React are both great frameworks but integrated you may run into the following issues when you build a complex, data heavy, highly interactive app.

See the examples/full example deployed at http://autovars-table.meteor.com to see the difference.

Github repo: https://github.com/Q42/autovars

1. Performance issues due to rerendering of entire subtrees

React is a great addition to Meteor for several reasons, one of them is it's components which allow you to encapsulate both view and logic. This is always a bit of a pain when you use Blaze.

Unfortunately if you have an app with many nested components, each with their own logic and derived state, rerendering those components may be too costly.

React was built with a nice shadow DOM to be able to quickly execute view changes. But that doesn't help when child components have their own set of calculations to run before they can render themselves. Those still have to run before every render.

One approach is to separate logic and view and keep the React components as dumb as possible. This is the approach Flux takes.

AutoVars goes in the other direction by making the components smarter so renders become more fine grained and less frequent. It relies heavily on core Meteor reactivity.

2. Bugs due to multiple state mutation flows: data, props and state

React has props to pass data between components and state to manage internal component state. The integration with Meteor adds .data and getMeteorData. Both render and getMeteorData become reactive and are executed when a reactive dependency they use changes.

This means both React and Meteor's Tracker can execute your code. They do so when they see fit. And they don't sync their timing.

This does not have to be a problem when you only use getMeteorData to pull in data from a Meteor Mongo collection and from there on program React style. This can be achieved with a strict code convention in your team.

Unfortunately when the team grows and you have more Meteor experts on the team, ReactiveVar's and autoruns may enter your project, possibly from other packages. The only way to connect those to the React world is through getMeteorData and then you will come to a point where it is very hard to understand what triggers executing your code.

AutoVars solves this problem by replacing .data and .state as well as most of the React component lifecycle with automatically executing functions, the results of which can be accessed through .autovars.

API

When you add the AutoVarMixin to your React component, the following will be added to the component.

this.constructAutoVars

This function is called once (during componentWillMount) and is the place where you can declare your Autovars. Autovars come in two flavors: primitive values that can be updated from other code and functions that are automatically rerun when the autovars (or other reactive dependencies) they use have changed.

App = React.createClass({
  mixins: [AutoVarMixin],

  constructAutoVars() {
    return {
      count: 0,
      oddOrEven: () => this.autovars.count.get() % 2 === 0 ? 'even' : 'odd'
    }
  }

The functions declared in constructAutoVars are executed in order and can therefore use the output of preceding sibling vars.

this.autovars

All Autovars declared in constructAutoVars are exposed through this.autovars. An Autovar is in fact a ReactiveVar and this.autovars gives you a handle to that ReactiveVar. This is particularly useful if you want to pass the var through React props, because with Autovars, only components actually reading from the ReactiveVar will be rerendered. With plain React, all components in the hierarchy passing on props are rerendered.

Example:

  click() {
    this.autovars.count.set(this.autovars.count.get() + 1);
  },

  render() {
    const count = this.autovars.count.get();
    const oddOrEven = this.autovars.oddOrEven.get();
    return (
      <div>
        <button onClick={this.click()}>Click Me</button>
        <p>{count} clicks ({oddOrEven}).</p>
      </div>)
  }

Show me an example!

See the examples directory for examples:

examples/simple: the autovars version of the default Meteor app examples/simple-todos-autovars: the autovars version of the simple-todos app examples/full: shows difference between passing props and using autovars

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].