Skip to content

Latest commit

 

History

History
78 lines (65 loc) · 3.13 KB

README.md

File metadata and controls

78 lines (65 loc) · 3.13 KB

Isomorphic React Relay

Adds server side rendering support to React Relay.

Thanks to @voideanvalue for the information that helped to build this package.

If you are using react-router-relay, then you might also be interested in isomorphic-relay-router, which is based on isomorphic-relay.

Installation

npm install -S isomorphic-relay

How to use

Make sure isomorphic-relay module is loaded before react-relay on the server, because it prevents "self is not defined" error (see facebook/fbjs#47).

Inject a network layer to isomorphic-relay (but not to Relay itself) on the server:

import {injectNetworkLayer} from 'isomorphic-relay';
injectNetworkLayer(new Relay.DefaultNetworkLayer('http://localhost:8080/graphql'));

Inject a no-op batching strategy into GraphQLStoreChangeEmitter on the server:

import GraphQLStoreChangeEmitter from 'react-relay/lib/GraphQLStoreChangeEmitter';
GraphQLStoreChangeEmitter.injectBatchingStrategy(() => {});

When processing a request on the server, preload data using loadAndStoreData, then render React using IsomorphicRootContainer in place of Relay.RootContainer, and send the React output along with the data to the client:

import {
  IsomorphicRootContainer,
  loadAndStoreData
} from 'isomorphic-relay';

app.get('/', (req, res, next) => {
  const rootContainerProps = {
    Component: MyContainer,
    route: new MyRoute(),
  };
  loadAndStoreData(rootContainerProps).then(data => {
    const reactOutput = ReactDOMServer.renderToString(
      <IsomorphicRootContainer {...rootContainerProps} />
    );
    res.render('index.ejs', {
      preloadedData: JSON.stringify(data),
      reactOutput
    });
  }, next);
});

On initial page load in the browser, store the preloaded data in the Relay store using storePreloadedData, then render React using IsomorphicRootContainer in place of Relay.RootContainer:

import {
  IsomorphicRootContainer,
  storePreloadedData,
} from 'isomorphic-relay';
import rootProps from './rootContainerProps';

const rootContainerProps = {
  Component: MyContainer,
  route: new MyRoute(),
};
const data = JSON.parse(document.getElementById('preloadedData').textContent);

storePreloadedData(rootContainerProps, data).then(render, render);

function render() {
  const rootElement = document.getElementById('root');

  ReactDOM.render(<IsomorphicRootContainer {...rootContainerProps} />, rootElement);
}

Important note: pass the same properties (i.e. containing the same Component, and the same route with the same route parameters) to loadAndStoreData on the server, to storePreloadedData in the browser, and to IsomorphicRootContainer both on the server, and in the browser on initial page load.

Example

See here.