Async rendering & data-fetching for universal React applications.

Last update: May 30, 2022

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

Async-rendering & data-fetching for universal React applications.

React Resolver lets you define data requirements per-component and will handle the nested, async rendering on both the server & client for you.

For example, the following will load & provide this.props.user for the UserProfile component:

import { resolve } from "react-resolver";

@resolve("user", function(props) {
  return http.get(`/api/users/${props.params.userId}`);
})
class UserProfile extends React.Component {
  render() {
    const { user } = this.props;
    ...
  }
}

This is the equivalent to asynchronously loading user and providing it to the component as if it were provided directly:

<UserProfile user={user} />

This makes components pure, stateless, and easy to test as a result.


Installation

For environments that don't have native Promise support, install ES6 Promise.

$ npm install --save react-resolver

For React v0.13 support, install v2.x.x.

$ npm install --save [email protected]

Documentation

Complete documentation can be found here:

http://ericclemmons.github.io/react-resolver/


Development

If you'd like to contribute to this project, all you need to do is clone this project and run:

$ npm install
$ npm test

Contributors

License

Internet Systems Consortium license

Copyright (c) 2015 Eric Clemmons

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Collaboration

If you have questions or issues, please open an issue!

GitHub

https://github.com/ericclemmons/react-resolver
Comments
  • 1. Prepare for React v0.13+

    Sebastian Markbåge wrote about Immutable Props here:

    http://facebook.github.io/react/blog/2015/02/24/streamlining-react-elements.html#immutable-props

    react-resolver does a "double mount/render": once componentWillMount to initially fire off a promise for data dependencies, then for the second pass to fill in the gaps in props:

    https://github.com/ericclemmons/react-resolver/blob/d6d3f5236af3c81913ef8da006a3671d47c2e41f/lib/mixin.js#L24-L25

    This technique is used because this.setProps and this.replaceProps can only be down on root-level components.

    The question is, will this pose any issues dynamic prop resolution with 0.13?

    /ping @sebmarkbage

    Reviewed by ericclemmons at 2015-02-24 21:34
  • 2. @client(Loader)

    I'd love to have a customized way of controlling when components are loading and when they have failed:

    @resolve({
      props: {
        users(props) {
          const url = `https://api.github.com/repos/${props.user}/${props.repo}/stargazers`;
          return axios.get(url).then(response => response.data);
        },
      },
    
      // client side only!
      loading(props) {
        // I can return a React component here and it'll render it in place of the component
        return <div>Loading...</div>
      },
    
      // server+client
      failed(props) {
        // or I can return an object and it'll pass those props to the component
        return { error: props.error, message: 'Oops' }
      }
    })
    class Stargazers extends React.Component { }
    
    Reviewed by goatslacker at 2015-04-26 21:25
  • 3. [HOLD] React Router v1 messes up with missing payload

    Hello. I'm trying to make a simple project with react-resolver + react-router. But it doesn't work. I've placed it here: https://github.com/alexbyk/react-resolver-example

    Could you pls take a look... what am I missing? The simple click action causes an error (without Resolver works fine): Uncaught TypeError: Cannot read property 'firstChild' of undefined && TypeError: deepestAncestor is undefined

    Reviewed by alexbyk at 2015-08-14 23:31
  • 4. owner-based and parent-based contexts differ

    On our internal project I saw:

    Warning: owner-based and parent-based contexts differ (values: [object Object] vs [object Object]) for key (parent) while mounting ResolverContainer (see: http://fb.me/react-context-by-parent)

    This may be related to #27, or it may be some subtle difference.

    (Although, there should be several updates in React v0.14 regarding context!)

    Reviewed by ericclemmons at 2015-04-15 22:15
  • 5. Issue with nested routes (React Router 1.0)

    I'm using React Router v1.0.3.


    I'm trying this kind of route hierarchy:

    -/ (top-level)
    --/ (home page)
    --/about (about page)
    --/friends (/friends route top-level, fetching of friends)
    ----/ (friends index; /friends)
    ----/list (friends list; /friends/list)
    

    (to code)

          <Route path="friends" component={Friends}>
            <Route path="/" component={FriendsIndex} />
            <Route path="list" component={FriendsList} />
          </Route>
    

    Where I am putting the Resolver container on the friends top-level component (Friends).

    Here's the stack trace:

    Uncaught (in promise) TypeError: Cannot read property 'ref' of undefined
        at cloneWithProps (http://localhost:1111/bundle.js:20673:13)
        at Friends.render (http://localhost:1111/bundle.js:23549:49)
        at ReactCompositeComponentMixin._renderValidatedComponentWithoutOwnerOrContext (http://localhost:1111/bundle.js:10462:34)
        at ReactCompositeComponentMixin._renderValidatedComponent (http://localhost:1111/bundle.js:10489:14)
        at ReactPerf.measure.wrapper (http://localhost:1111/bundle.js:16948:21)
        at ReactCompositeComponentMixin.mountComponent (http://localhost:1111/bundle.js:9910:30)
        at ReactPerf.measure.wrapper [as mountComponent] (http://localhost:1111/bundle.js:16948:21)
        at Object.ReactReconciler.mountComponent (http://localhost:1111/bundle.js:17763:35)
        at ReactCompositeComponentMixin._updateRenderedComponent (http://localhost:1111/bundle.js:10437:40)
        at ReactCompositeComponentMixin._performComponentUpdate (http://localhost:1111/bundle.js:10399:10)
    

    Check this repo http://srph.github.io/rrt/#/friends (now https://github.com/srph/playground/tree/master/react/react-resolver-prop-bug)

    Not sure what I'm doing wrong haha.

    Edit (8/27/2014): Repository transferred to https://github.com/srph/playground/tree/master/react/react-resolver-prop-bug (link to demo)

    Reviewed by srph at 2015-07-21 11:23
  • 6. Idea: Provide a dependency-less build

    I believe there is value in keeping bluebird, however if you're running in an ES6-shimmed environment then you already having promises support making bluebird redundant. It would be great to provide a build that has no dependencies this way you get a minimal react-resolver.

    Reviewed by goatslacker at 2015-03-11 17:45
  • 7. Fix HistoryLocation in React v0.13 Example

    Hi!

    Using HistoryLocation, instead of RefreshLocation as used in the examples, I'm only able to navigate via react-router (both Link component and transitionTo('')) once pr. page load. I've tried to fiddle around with both the source for react-router and react-resolver, but without success. The URL changes, but the

    I've reduced my issue down to this repo, which can be run with npm install and npm run watch. If you uncomment 11th line and comment the 10th line in src/client.js, you'll notice that routing works, but obviously serverside rendering does not. This leads me to think this could be a Resolver problem.

    Anyone having the same issue? Have I done something wrong? I've tried to implement Resolver as per the examples as close as possible.

    Reviewed by ostrgard at 2015-08-12 15:03
  • 8. Async streaming data updates (eg Flux)

    Since react-resolver uses promise wrappers around callbacks, it may have a problem with wiring up with Flux stores that have callbacks that could be called multiple times with data.

    I have a Flux library Hoverboard that works with subscribing to a callback function. As changes come through the store via user actions, the data updates asynchronously. This works well with solve (I built them to work together in a Flux framework).

    Put more simply, react-resolver may need to be modified to work with the following code:

    statics: {
        resolve: {
            count: function(done) {
                var count = 1;
                setInterval(function(){
                    done(count++);
                }, 1000);
            }
        }
    }
    

    Thoughts?

    Reviewed by jesseskinner at 2015-02-20 16:45
  • 9. React v0.14

    It's coming!

    http://facebook.github.io/react/blog/2015/09/10/react-v0.14-rc1.html

    Plus, this will improve the API for rendering. Luckily, the code already has @TODO messages for where the replacements need to happen.

    Reviewed by ericclemmons at 2015-09-11 01:53
  • 10. Bootstrap client-side data

    • Need to expose resolver.states for serialization and output on the server.
    • Client needs to bootstrap new Resolver(window.__resolver__) or something .
    Reviewed by ericclemmons at 2015-04-14 03:56
  • 11. Update react-router example

    In the newest react-router, the server side rendering and client side rendering has changed a lot so I'm no longer sure of how to use . Would love to get some help in terms of an updated example for react-router.

    Reviewed by geekyme at 2015-09-21 15:01
  • 12. Fix compatibility with Babel 6

    Hello,

    Thank you for this awesome project !

    I just tried to import react-resolver on one of my new project, and I found out that your babel configuration is not compatible with the new Babel versions.

    Your .babelrc contain the following:

    {
      "stage": 0
    }
    

    Which is not valid anymore.

    This should be replaced by the following:

    {
      "presets": ["stage-0"]
    }
    

    Thank you


    Edit: The error displayed when compiling with babel 6 is the following:

    ERROR in ./~/react-resolver/dist/index.js Module build failed: ReferenceError: [BABEL] node_modules\react-resolver\dist\index.js: Using removed Babel 5 option: node_modules\react-resolver.babelrc.stage - Check out the corresponding stage-x presets http://babeljs.io/docs/plugins/#presets at Logger.error (node_modules\babel-core\lib\transformation\file\logger.js:41:11) at OptionManager.mergeOptions (node_modules\babel-core\lib\transformation\file\options\option-manager.js:220:20) at OptionManager.init (node_modules\babel-core\lib\transformation\file\options\option-manager.js:368:12) at File.initOptions (node_modules\babel-core\lib\transformation\file\index.js:212:65) at new File (node_modules\babel-core\lib\transformation\file\index.js:135:24) at Pipeline.transform (node_modules\babel-core\lib\transformation\pipeline.js:46:16) at transpile (node_modules\babel-loader\lib\index.js:46:20) at Object.module.exports (node_modules\babel-loader\lib\index.js:163:20)

    Reviewed by Paul-DS at 2018-11-04 11:17
  • 13. Need hydrate static method in the Resolver class for server side rendering

    With react 16 there is a new method called hydrate specifically for server rendered apps https://reactjs.org/docs/react-dom.html#hydrate

    Please add a method to the Resolver component to optionally hydrate an application.

    Reviewed by viveksanthosh at 2018-06-21 05:46
  • 14. "[email protected]" has incorrect peer dependency "[email protected]^0.14.6 || ^15.0.0-0"

    I'm trying to upgrade react to v16, but there seems to be some issues with the dependencies from the latest version of react-resolver. Any ideas on how to resolve this?

    Reviewed by janicetyp at 2017-11-06 09:17
  • 15. Using @client and @resolve on the same class causes @resolve to be called twice

    Reproduction test case

    import React, {Component} from 'react'; 
    import { resolve, client } from "react-resolver";
    import Promise from 'bluebird';
    
    export class SearchPage extends Component {                                        
        render() {
            console.log("Re-Rendering: ", this.props.user);                               
            return <div>
                Prop: {this.props.user}
            </div>
        }
    }
    // uncomment this and you'll see "Waiting on response" and "Resolving" repeated twice in the console
    /*
    @client(() => {
        return <div>Loading...</div>
    })
     */
    @resolve({
        "user": function(props) {
            console.log("Waiting on response, ", props);
            return new Promise((resolve,reject) => {
                setTimeout(() => {
                    console.log("Resolving");
                    resolve("ayyyyyy");
                }, 5000)
            })
        }
    })
    export default class InnerSearchPage extends SearchPage {};
    

    Expected Output [with or without server side rendering, eg, React Router switching pages. This is the observed behavior without @client(...)]

    Waiting on response,  Object { [abridged] }
    Resolving
    USER PROP:  ayyyyyy
    

    Actual Output [with or without server side rendering]

    Waiting on response,  Object { [abridged] }
    Resolving
    USER PROP:  ayyyyyy
    Waiting on response,  Object { [abridged] }
    Resolving
    USER PROP:  ayyyyyy
    

    Notes

    I'm using server-side rendering, but the behavior is unchanged when I remove window.__REACT_RESOLVER_PAYLOAD__. I am using HOC as a parent of this component. Some Versions. I don't know how much of this is relevant.

    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "react-redux": "^5.0.5",
    "react-resolver": "^3.1.0",
    "react-router": "^4.1.1",
    "react-router-dom": "^4.1.1",
    "redux": "^3.7.0",
    
    Reviewed by liamzdenek at 2017-07-13 22:46
An immutable data store for managing deeply nested structure with React

Cortex is an immutable data store for managing deeply nested structure with React Key features: supports deeply nested data uses immutable data, which

May 20, 2022
Immutable data structures with history for top-to-bottom properties in component based libraries like React. Based on Immutable.js

Immstruct A wrapper for Immutable.js to easily create cursors that notify when they are updated. Handy for use with immutable pure components for view

Jul 15, 2021
A library for writing React components that automatically manage subscriptions to data sources simply by accessing them

ReSub A library for writing better React components and data stores. Uses automatic subscriptions to reduce code and avoid common data flow pitfalls.

May 11, 2022
Immutable persistent data collections for Javascript which increase efficiency and simplicity.
Immutable persistent data collections for Javascript which increase efficiency and simplicity.

Immutable collections for JavaScript Immutable data cannot be changed once created, leading to much simpler application development, no defensive copy

Jun 24, 2022
A tree data structure that emits events on updates, even if the modification is triggered by one of the leaves, making it easier to think in a reactive way.
A tree data structure that emits events on updates, even if the modification is triggered by one of the leaves, making it easier to think in a reactive way.

Freezer A tree data structure that emits events on updates, even if the modification is emited by one of the leaves, making it easier to think in a re

Jun 18, 2022
JavaScript & TypeScript persistent and optionally immutable data tree with cursors.

Baobab Baobab is a JavaScript & TypeScript persistent and immutable (at least by default) data tree supporting cursors and enabling developers to easi

Jun 15, 2022
Immutable data structures for JavaScript which are backwards-compatible with normal JS Arrays and Objects.

seamless-immutable Immutable JS data structures which are backwards-compatible with normal Arrays and Objects. Use them in for loops, pass them to fun

Jun 18, 2022
Immutable persistent data collections for Javascript which increase efficiency and simplicity.
Immutable persistent data collections for Javascript which increase efficiency and simplicity.

Immutable collections for JavaScript Chat on slack Read the docs and eat your vegetables. Docs are automatically generated from README.md and immutabl

Jun 23, 2022
🍉 Reactive & asynchronous database for powerful React and React Native apps ⚡️
🍉 Reactive & asynchronous database for powerful React and React Native apps ⚡️

A reactive database framework Build powerful React and React Native apps that scale from hundreds to tens of thousands of records and remain fast ⚡️ W

Jun 19, 2022
Highly Composable MVVM Framework for React

Astarisx Highly Composable MVVM Framework for React. Click here for the Astarisx Website and Documentation Highly Composable UI Components Astarisx Vi

Aug 13, 2019
Morearty.js - centralized state management for React in pure JavaScript

Morearty.js ![Gitter](https://badges.gitter.im/Join Chat.svg) Introduction Download Dependencies Current status Documentation Usage TodoMVC App compon

Jan 27, 2022
React integration for Baobab.

baobab-react Welcome to baobab's React integration (from v2.0.0 and onwards). Implemented patterns: Hooks Higher order components (curried so also usa

Jun 1, 2022
A tiny and unobtrusive state management library for React and Preact apps

statty A tiny and unobtrusive state management library for React and Preact apps The current size of statty/dist/statty.umd.min.js is: The problem Mos

Jun 6, 2022
React, but with built-in global state management.
React, but with built-in global state management.

ReactN ReactN is an extension of React that includes global state management. It treats global state as if it were built into React itself -- without

Jun 21, 2022
experimental project for babel-plugin-mutable-react-state

Goalist Mutable React Example This example is an attempt to work with babel-plugin-mutable-react-state on a simpler project to see how complicated wou

Jun 7, 2022
Async rendering & data-fetching for universal React applications.

React Resolver Async-rendering & data-fetching for universal React applications. React Resolver lets you define data requirements per-component and wi

May 30, 2022
Universal data fetching and route lifecycle management for React etc.

redial Universal data fetching and route lifecycle management for React etc. $ npm install --save redial Why? When using something like React Router,

Jun 6, 2022
A universal boilerplate for building web applications w/ TypeScript, React, Redux, Server Side Rendering and more.

Vortigern Vortigern is our opinionated boilerplate for crafting universal web applications by using modern technologies like TypeScript, React and Red

Mar 25, 2022
Resources for use with ember-data for reactive data (re)fetching

ember-data-resources Resources for reactive data fetching with ember-data Compatibility Ember.js v3.25 or above Installation ember install ember-data-

May 30, 2022
Async HTTP request data for axios. Designed for diverse UI states, SSR and data pre-caching.

React useApi() Axios-based React hooks for async HTTP request data. react-use-api feeds API data to React components when SSR (Server-Side Rendering),

May 26, 2022