GithubHelp home page GithubHelp logo

isabella232 / react-redata Goto Github PK

View Code? Open in Web Editor NEW

This project forked from moxystudio/react-redata

0.0 0.0 0.0 168 KB

React data container for isomorphic applications, providing a unified and performant load & reload pattern

License: MIT License

JavaScript 100.00%

react-redata's Introduction

redata

DISCLAIMER: THIS MODULE IS COMPLETELY WORK IN PROGRESS, AND WILL BE FOR THE NEXT FEW DAYS. IF YOU LIKE THE WORK SO FAR, KEEP AN EYE OUT, WE SHOULD BE RELEASING A STABLE VERSION IN A WEEK OR SO.

NPM version Downloads Build Status Dependency status Dev Dependency status

React data container for isomorphic applications, providing a unified and performant load & reload pattern.

The motivation behind redata is to create a flexible, efficient and simple solution for isomorphic react components to asynchronously load information. A few driving concepts behind redata:

  • You should only need to write your loading routines once, and it should run both on the server and client without any added control.
  • The component should automatically react (pun intended) to prop changes and potentially reload the data if necessary.
  • In case a prop change does not affect the relevance of the already loaded data, the loaded data should be reused automatically.
  • Loading data might require a single async operation, but it also might require multiple operations, and you should be able to inspect progress on a granular level if needed, but also be able to quickly understand if everything is loaded, loading, or errored, in case you don't need the granularity.
  • It should be useful and easy to use if you're just using React, but also if you're using React + Redux.
  • It should be compatible with ReactNative.
  • It should sound like a verb, so you can say something like you just need to redata the component, meaning that the data will load & reload automatically and in a consistent fashion.

Installation

$ npm install --save redata

Usage

Here's an example of how you would redata a ShoppingBag component which requires that the contents of the bag be loaded via a fetchBag() that already exists, and returns a Promise:

import React, { PureComponent, PropTypes } from 'react';
import { reactRedata } from 'redata';
import fetchBag from './fetchBag';

class ShoppingBag extends PureComponent {
	render() {
		const { result, loading, error } = this.props;

		// Loading and error are provided by redata, but you can rename
		// or even drop any property that you don't need in the mapper.
		if (error || loading) {
			return null; // you could render an error message or loading respectively
		}

		return (
			<ul>{ result.map((item) => (
				<li key={ item.id }>{ item.name }</li>
			)) }</ul>
		);
	}
}

ShoppingBag.propTypes = {
	bagId: PropTypes.number.isRequired,
	loading: PropTypes.bool,
	error: PropTypes.instanceOf(Error),
	result: PropTypes.array,
};

export default reactRedata(
	({ nextProps }) => fetchBag(nextProps.bagId),              // loader
	({ props, nextProps }) => props.bagId !== nextProps.bagId, // shouldReload policy
)(ShoppingBag);

reactRedata is a Higher Order Component with the following signature:

reactRedata(loader[, shouldReload, mapper, initialCtx])(WrappedComponent)
  • loader: The function that is responsible for loading the data. Function is invoked with ({ props, nextProps, state, nextState, data }, onUpdate) and should return a Promise for the retrieved data. Your loader can call onUpdate in order to provide progressive data or somehow data that changes throughout time.
  • shouldReload (optional):
    • Function that decides whether the data should be reloaded or not, should return boolean.
    • Called every time props or state changes, and defaults to ({ props, nextProps, state, nextState, data }) => false, meaning that by default the data is only loaded once, and reused until the component is unmounted. data refers to the result of the last redata.
  • mapper (optional):
    • Function that is called after the loader, and defaults to an identity function, or (data) => data. data is an object containing:
      • loading: true if the loader is still running, false otherwise.
      • error: An instance of Error in case the loader failed, undefined otherwise.
      • result: The result of the loader, or undefined if the loader is still running.
    • The return value of this function is spread as props for your component.
  • initialCtx (optional): Initial context for new redatas. This can be useful for situations in which you have previously obtained data that has been stored and possibly serialised, as in server side renders. Defaults to { lastData: undefined, /* Last loaded data */ final: false // Whether lastData is result of the resolved promise or result of onUpdate */ }.

The nitty-gritty details

So you're interested in understanding how redata works under the hood. That's awesome.

The motivation behind redata is already explained in the introduction, but in order to get it to work, there were a few pitfalls that we had to avoid.

In terms of the server side rendering, the way that redata discovers async dependencies in data is inspired by Apollo.

Here's a breakdown of how the whole redata flow works:

  • Server:
  • Client:
    1. redata component is rendered for the first time.
    2. Checks a global store for any previously loaded data. In React, a really hard to collide and predictable key is stored in window by the server-side render, which is then accessed by the client.
    3. If data was loaded, the redata cycle is restarted, by calling the shouldReload function, which determines if the data is still good, or if it needs to reload.
    4. If data is still good, the data is returned, which can mean one of two things:
      • redata is wrapping a component: data is spread and injected as props into the underlying component.
      • redata is not wrapping a component, typically because it is composing a larger redata: the promise that was returned by redata resolves.
    5. If data is no longer good, the loader is called.

TODO

  • react-redata:
    • Traverse tree, find redatas, wait for them to resolve, and store data in global store for client to pick up on.
    • Provide state and nextState to shouldReload.
  • redata:
  • Misc:
    • Update README.
    • Draw simple diagram explaining the data flow in redata.
    • Unit tests overall.

License

MIT License

react-redata's People

Contributors

antoniocapelo avatar marcooliveira avatar satazor avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.