mattmccray / react-resolver

Isomorphic library to recursively lazy-load data for React components

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

React Resolver https://img.shields.io/npm/v/react-resolver.svg

Isomorphic library to recursively lazy-load data for React components

  • Define & lazy-load component data dependencies and inject them as props.
  • Express/Koa/Hapi-friendly server-side rendering.
  • Progressive, client-side rendering.
  • Works with React Router.


Intro

Similar to ui-router for Angular, React Resolver lets you define & load data dependencies as close to the templates using them as possible: the Components.

You may be asking, how is this different from Relay & GraphQL?

Both projects are working to solve the similar problems:

Data fetching is still a tricky problem, especially as applications become more complicated.

With Relay & GraphQL:

Each component specifies its own data dependencies declaratively using a query language called GraphQL. The data is made available to the component via properties on this.props.

(Emphasis my own)

With React Router, whether you use Flux-like Stores, hand-crafted Services, or even isomorphic HTTP libraries like superagent, is up to you.

Once Relay is released, you should be to make a smooth transition (if you'd like!), as your templates should still be expecting the same data via this.props.

Installation

$ npm install --save react-resolver
var Resolver = require('react-resolver');

// Create an instance
var resolver = new Resolver();

// or, if you prefer factories...
var resolver = Resolver.create();

Usage

1. Specify Props to Lazy-Load

var Resolver = require('react-resolver');

var UserView = React.createClass({
  mixins: [Resolver.mixin],

  statics: {
    resolve: {
      // Return a Promise
      user: function() {
        return UserStore.find(this.getParams().userId);
      },

      // or use a Callback
      user: function(done) {
        request.get(`/users/${this.getParams().userId}`, done);
      }
    }
  },
  ...
});

2. Wrap your <Route />

Assuming you're using React Router, you'll need to wrap your routes to maintain context:

var resolver  = require('resolver').create();
var routes    = resolver.route(require('./routes'));

This makes it possible for your statics.resolve props to access Router.State, Router.Navigation, and other contexts.

3. Resolve & Render

Client

Because the client supports lazy-loading of components, you can use React.render as usual.

The only caveat is, if you're using react-router, you'll need to wrap your routes with resolver.route to maintain context:

var Resolver  = require('resolver');
var routes    = require('./routes');

var resolver = Resolver.create();

Router.run(resolver.route(routes), function(Handler) {
  React.render(<Handler />, document.getElementById('app'));
});

Server

On the server, all promises have to be resolved before rendering and sending the response via resolver.resolve.

Be sure to create a new instance of the Resolver per-request to avoid leaking props to different users!

var Resolver  = require('resolver')
var routes    = require('./routes');

// Your middleware here...
app.get('/', function(req, res) {
  var resolver = Resolver.create();

  Router.run(resolver.route(routes), function(Handler) {
    resolver.resolve(<Handler />).then(function(handled) {
      res.send(React.renderToStaticMarkup(handled));
    });
  });
});

Development

$ npm install
$ npm link .
$ (cd examples/contacts/ && npm link react-resolver)
$ npm test

Authors

About

Isomorphic library to recursively lazy-load data for React components

License:Other


Languages

Language:JavaScript 98.0%Language:HTML 1.6%Language:CSS 0.5%