React Data SSR
This package provides a High Order Component to make SSR and data fetching painless.
Instalation
yarn -i react-data-ssr
npm -i react-data-ssr --save
Examples
The examples folder contains several exmaples.
Usage
Simple Example
import React from 'react';
import PropTypes from 'prop-types';
import { withGetInitialData } from 'react-data-ssr';
const List = ({isLoading, list}) => {
if (isLoading)
return <span>Loading</span>;
return (
<div>
<h1>List</h1>
<ul>
{(list||[]).map((l, i) => <li key={i}>${l}</li>)}
</ul>
</div>
);
};
List.propTypes = {
isLoading: PropTypes.bool,
list: PropTypes.array,
};
const mapDataToProps = ({data}) => ({
list: data,
});
const getData = (props, {setLoading, setData}) => new Promise(rs => {
setLoading(true);
setTimeout(() => {
setData({
data: [
'first',
'second',
'thrid',
]
});
rs();
}, 1000);
});
export default withGetInitialData({
mapDataToProps,
getData,
})(List);
import { hydrate } from 'react-dom';
import List from './List';
const data = window.__INITIAL_DATA__;
hydrate(
<List
hasLoadedComponent={k => k in data}
dismissLoadedComponent={k => delete data[k]}
getInitialData={k => data[k]}
/>,
document.getElementById('root')
);
Note: The example uses React 16, but it's not a requeriment. React 15 could alse be used.
Api
withGetInitialData(options)
Create a high-order React component class that fetches data server side and re uses the data in client side (or fetches it if it isn't available).
options
getData: (props: Object, bag: Object) => Promise
This function is called to perform the fetch of the data.
props
: The component properties, on server side they are created by mapArgsToProps
function.bag
: An object with two methods:
setLoading: (b: bool) => null
: To set the isLoading
property.setData: (data: Object) => null
: To set the data
, it will set isLoading
to false
.
Note: Server and client will call the same function, in order to provide different data fetching logic, one could use Webpack's Normal Module Replacement Plugin and implement a package with the same inteface.
Note: This function is required
mapDataToProps: (data: Object, ownProps: Object) => Object
This function is used to map the data fetched to component properties.
The result of this function must be a plain object that will be merged to the component's props.
data
: Is the data
object setted with the setData
function in the getData
phase.ownProps
: Is an object with the props of the component
Note: This function is required
This function is used to build the component's props on server side.
branch: Object
: Data resolution is done by passing an array of React Router Config's Branches, Objects or Components to resolveInitialData
function. branch
is the current item of that array. _The branch
argument passed to the getInitialData
static method_.extra?: Object
: The extra argument passed to the getInitialData
static method or to resolveInitialData
.
During SSR, in order to fetch data, the component's static method getInitialData
will be called. mapArgsToProps
is used to map the arguments passed to that static method into the component's props.
shouldGetData?: (props: Object, nextProps: Object) => boolean
(optional)
Function used to check if should get data in the componentWillReceiveProps
phase. The purpose of this function is to allow the re fetch of data if the properties passed to the Component have changed. By default, this function always returns false.
It receives two parameters:
props: Object
: The current Component properties.nextProps: Object
: The next Component properties.
generateComponentKey?: (component: ReactComponent, props: Object) => String
(optional)
Server side data and client side data is related by a component key. By default, each Component has an auto incremented key which is generated by the import order (we are assuming that the client and the server will import components in the same order).
There are some cases (1), when we will need to make the key to depend of the component properties.
1: The simplest example is when data fetching depends on React Router's Match. On client side, we will want to re fetch when the url is change, this won't trigger an unmount, but a componentWillReceiveProps.
Injected props and methods
Props
All the mapped properties by the mapDataToProps
function.
<WithGetInitialDataComponent />
<WithGetInitialDataComponent />
refers to the components created by the withGetInitialData(options)
function.
Props
This section describes the properties that could be passed to the Component.
getInitialData: (key: String) => Object
A function that is used to retrieve the initial data through the component key.
hasLoadedComponent: (key: String) => bool
A function that is used to check if a Component (through it's key) has his data available.
dismissLoadedComponent: (key:String) => null
A function that is used to dismiss a previously loaded data.
A component will dismiss when it's unmounted (or when it's properties have changed and shouldGetData
returned true
).
Methods
This section describes the methods provided by the Component.
This method should be called server side in order to fetch the component data. It will return a Promise which will be resolved when the data has been fetched. The result of the promise is the data fetched (setted by the setData
function called in getInitialData
).
branch?: Object
: Data resolution is done by passing an array of React Router Config's Branches, Objects or Components to resolveInitialData
function. branch
is the current item of that array. The branch
argument passed to the getInitialData
static method.extra?: Object
: Extra argument that will be used to in order to build the Component's prop. See mapArgsToProps
.