relay-tools/react-router-relay

Name: react-router-relay

Owner: Relay Tools

Description: Relay integration for React Router

Created: 2015-08-18 03:07:05.0

Updated: 2018-01-09 21:34:26.0

Pushed: 2017-08-14 21:03:36.0

Homepage:

Size: 216

Language: JavaScript

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

react-router-relay Travis npm

Relay integration for React Router.

This library only supports Relay Classic. For Relay Modern support, see Found Relay.

This library does not support React Router v4, because React Router v4 does not provide the necessary integration points for efficient data fetching with Relay. Additionally, rendering performance will be better with React Router v2 than with React Router v3, as the link subscription logic in React Router v3 triggers unnecessary rerenders with Relay.

Discord

Usage

Apply the useRelay router middleware, pass in a Relay environment to <Router>, then define Relay queries and render callbacks for each of your routes:

rt { applyRouterMiddleware, /* ... */ } from 'react-router';
rt useRelay from 'react-router-relay';

.. */

t ViewerQueries = {
ewer: () => Relay.QL`query { viewer }`


t WidgetQueries = {
dget: () => Relay.QL`query { widget(widgetId: $widgetId) }`


tDOM.render(
outer
history={history}
render={applyRouterMiddleware(useRelay)}
environment={Relay.Store}

<Route
  path="/"
  component={Application}
  queries={ViewerQueries}
>
  <Route path="widgets">
    <IndexRoute
      component={WidgetList}
      queries={ViewerQueries}
      prepareParams={prepareWidgetListParams}
    />
    <Route
      path=":widgetId"
      component={Widget}
      queries={WidgetQueries}
      render={({ props }) => props ? <Widget {...props} /> : <Loading />}
    />
  </Route>
</Route>
Router>,
ntainer

react-router-relay will automatically generate a combined Relay query config with all queries and parameters from the active React Router routes, then pass down the query results to each of the route components. As the queries are all gathered onto a single query config, they'll all be fetched in parallel, and the data for your entire page will load and then render in one go.

You can find an example implementation of TodoMVC with routing using react-router-relay at https://github.com/taion/relay-todomvc.

Guide
Installation
m install react react-dom react-relay react-router
m install react-router-relay
Router configuration

Apply the useRelay router middleware, and pass in a Relay environment to the <Router>:

rt useRelay from 'react-router-relay';

.. */

tDOM.render(
outer
history={history}
routes={routes}
render={applyRouterMiddleware(useRelay)}
environment={Relay.Store}
,
ntainer

Routes and queries
Basic configuration

For each of your routes that requires data from Relay, define a queries prop on the <Route>. These should be just like the queries on a Relay query config:

t ViewerQueries = {
ewer: () => Relay.QL`query { viewer }`


t applicationRoute = (
oute
path="/"
component={Application}
queries={ViewerQueries}


Just like with Relay.Renderer, the component will receive the query results as props, in addition to the other injected props from React Router.

If your route doesn't have any dependencies on Relay data, just don't declare queries. The only requirement is that any route that does define queries must have a Relay container as its component.

If your route's Relay data dependencies are a function of the location or of the parameters, you can define a getQueries function on your route that returns the computed queries as a function of the current router state:

te
mponent={Widget}
tQueries={({ location, params }) => getWidgetQueries(location, params)}

Path parameters

Any path parameters for routes with queries and their ancestors will be used as parameters on the Relay query config:

t WidgetQueries = {
dget: () => Relay.QL`
query {
  widget(widgetId: $widgetId), # $widgetId comes from the path.
}



t Widget = Relay.createContainer(/* ... */, {
agments: {
widget: () => Relay.QL`
  fragment on Widget {
    name,
  }
`



his handles e.g. /widgets/3.
t widgetRoute = (
oute
path="widgets/:widgetId"
component={Widget}
queries={WidgetQueries}


Additional parameters

If your queries require additional parameters from the location, such as from the location query or state, you can add those parameters with prepareParams. You can also use prepareParams to do additional conversion or initialization of your parameters.

The prepareParams method has the same signature and behavior as prepareParams on a Relay query config, except that it also receives the current router state as an argument. It is expected to return the same result when given the same previous params and router state.

Additionally, you can use route parameters as variables on your containers:

t WidgetList = Relay.createContainer(/* ... */, {
itialVariables: {
color: null,
size: null,
limit: null


agments: {
viewer: () => Relay.QL`
  fragment on User {
    widgets(color: $color, size: $size, first: $limit) {
      edges {
        node {
          name,
        },
      },
    },
  }
`



tion prepareWidgetListParams(params, { location }) {
nst { color, size } = location.query;
nst limit = location.state && location.state.limit;

turn {
...params,
color,
size: size && parseInt(size, 10),
limit: limit || 10,



his handles e.g. /widgets?color=blue&size=3.
t widgetListRoute = (
oute
path="widgets"
component={WidgetList}
queries={ViewerQueries}
prepareParams={prepareWidgetListParams}


Named components

For routes with named components, define queries as an object with the queries for each component by name:

te
mponents={{ foo: FooComponent, bar: BarComponent }}
eries={{ foo: FooQueries, bar: BarQueries }}

Render callback

You can pass in a custom render callback to your routes:

te
mponent={WidgetList}
eries={ViewerQueries}
nder={({ props }) => props ? <WidgetList {...props} /> : <Loading />}

This has the same signature as the render callback on Relay.Renderer, except that, when present, props will also include the injected props from React Router. As on Relay.Renderer, you can return undefined to continuing rendering the last view rendered.

While transitioning, the ready state properties (done, error, retry, stale) will reflect the ready state of the transition as a whole. However, the props object in the render callback for a route will be populated as long as the data for that particular route are ready. For example, if a transition does not change the params to the queries for a parent route, the render callback for that route will have props, even while the render callbacks for its child routes may not.

The argument object to the render callback includes two extra properties: routerProps and element. routerProps contains the props from the router, and unlike props, will be populated regardless of the Relay ready state. routerProps can be used to render child routes while the data for the parent route are still loading, or to otherwise use information from the router to control rendering before the Relay data are available. element contains the base route element without the props from Relay, and can be used to render the route component when the route uses a dynamic component, or when using other router middlewares that may wrap the route component:

rops, routerProps, element }) => {
 (!props) {
return <Loading {...routerProps} />;


turn React.cloneElement(element, props);

When using named components, you can define these on a per-component basis, optionally omitting the callback for components that do not need a custom render callback:

te
mponents={{ foo: FooComponent, bar: BarComponent }}
eries={{ foo: FooQueries, bar: BarQueries }}
nder={{ foo: renderFoo }}

Additional Relay.Renderer configuration

We pass through additional props on <Router> or the generated router context to the underlying Relay.Renderer. You can use this to control props like forceFetch on the Relay.Renderer:

ter
story={history}
utes={routes}
nder={applyRouterMiddleware(useRelay)}
rceFetch={true}
vironment={Relay.Store}

Notes
Authors

This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.