Skip to content

Commit

Permalink
Update additional parameter handling
Browse files Browse the repository at this point in the history
  • Loading branch information
taion committed Apr 26, 2016
1 parent 3ca0386 commit 91884b6
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 85 deletions.
33 changes: 15 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ ReactDOM.render((
<IndexRoute
component={WidgetList}
queries={ViewerQueries}
queryParams={['color']} stateParams={['limit']}
prepareParams={prepareWidgetListParams}
/>
<Route
Expand Down Expand Up @@ -105,9 +104,7 @@ const WidgetQueries = {
`
}

class Widget extends React.Component { /* ... */ }

Widget = Relay.createContainer(Widget, {
const Widget = Relay.createContainer(/* ... */, {
fragments: {
widget: () => Relay.QL`
fragment on Widget {
Expand All @@ -128,16 +125,14 @@ const widgetRoute = (

#### Additional parameters

If your query requires parameters from the location query or state, you can specify them respectively on the `queryParams` or `stateParams` props on the `<Route>`. URL and query parameters will be strings, while missing query and state parameters will be `null`.
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.

If you need to convert or initialize these parameters, you can do so with `prepareParams`, which has the same signature and behavior as `prepareVariables` on a Relay container, except that it also receives the React Router route object as an argument.
The `prepareParams` method has the same signature and behavior as `prepareParams` on a Relay query config, except that it also receives the current location as an argument.

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

```js
class WidgetList extends React.Component { /* ... */ }

WidgetList = Relay.createContainer(WidgetList, {
const WidgetList = Relay.createContainer(/* ... */, {
initialVariables: {
color: null,
size: null,
Expand All @@ -150,20 +145,24 @@ WidgetList = Relay.createContainer(WidgetList, {
widgets(color: $color, size: $size, first: $limit) {
edges {
node {
name
}
}
}
name,
},
},
},
}
`
}
});

function prepareWidgetListParams(params, route) {
function prepareWidgetListParams(params, location) {
const { color, size } = location.query;
const limit = location.state && location.state.limit;

return {
...params,
size: params.size ? parseInt(params.size, 10) : null,
limit: params.limit || route.defaultLimit
color,
size: size && parseInt(size, 10),
limit: limit || 10,
};
};

Expand All @@ -172,9 +171,7 @@ const widgetListRoute = (
<Route
path="widgets" component={WidgetList}
queries={ViewerQueries}
queryParams={['color', 'size']} stateParams={['limit']}
prepareParams={prepareWidgetListParams}
defaultLimit={10}
/>
);
```
Expand Down
20 changes: 13 additions & 7 deletions src/QueryAggregator.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import invariant from 'invariant';
import isEqual from 'lodash/isEqual';
import Relay from 'react-relay';

import getParamsForRoute from './utils/getParamsForRoute';
import getRouteQueries from './utils/getRouteQueries';
import mergeRouteParams from './utils/mergeRouteParams';

const DEFAULT_KEY = '@@default';

Expand All @@ -25,7 +25,7 @@ export default class QueryAggregator {
}

updateQueryConfig(routerProps) {
const { routes, components, params, location } = routerProps;
const { routes, components } = routerProps;

const queryConfig = {
name: null,
Expand Down Expand Up @@ -71,9 +71,9 @@ export default class QueryAggregator {
component.displayName || component.name
);

const routeParams =
getParamsForRoute({ route, routes, params, location });
Object.assign(queryConfig.params, routeParams);
queryConfig.params = mergeRouteParams(
queryConfig.params, route, routerProps
);

Object.keys(queries).forEach(queryName => {
const query = queries[queryName];
Expand All @@ -89,9 +89,15 @@ export default class QueryAggregator {
// routes.
wrappedQuery = () => query();
} else {
// We just need the query function to have > 0 arguments.
// When not using the shorthand, we can control the injected
// params, so restrict them to just the ones for the current route
// and its ancestors.
const paramsForRoute = queryConfig.params;

// We need the query function to have > 0 arguments to hit the code
// path for non-shorthand queries.
/* eslint-disable no-unused-vars */
wrappedQuery = _ => query(component, routeParams);
wrappedQuery = _ => query(component, paramsForRoute);
/* eslint-enable */
}

Expand Down
14 changes: 11 additions & 3 deletions src/RouteContainer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import StaticContainer from 'react-static-container';

import getParamsForRoute from './utils/getParamsForRoute';
import mergeRouteParams from './utils/mergeRouteParams';

const propTypes = {
queries: React.PropTypes.object.isRequired,
Expand All @@ -17,9 +17,17 @@ function RouteContainer(
{ queries, routerProps, children, ...extraProps },
{ queryAggregator }
) {
const { key, route } = routerProps;
const { key, route, routes } = routerProps;

let params = {};
for (const ancestorRoute of routes) {
params = mergeRouteParams(params, ancestorRoute, routerProps);

if (ancestorRoute === route) {
break;
}
}

const params = getParamsForRoute(routerProps);
const renderArgs =
queryAggregator.getRenderArgs(route, key, queries, params);

Expand Down
52 changes: 0 additions & 52 deletions src/utils/getParamsForRoute.js

This file was deleted.

15 changes: 15 additions & 0 deletions src/utils/mergeRouteParams.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import getRouteParams from 'react-router/lib/getRouteParams';

export default function mergeRouteParams(prevParams, route, routerProps) {
const params = {
...prevParams,
...getRouteParams(route, routerProps.params),
};

const { prepareParams } = route;
if (!prepareParams) {
return params;
}

return prepareParams(params, routerProps.location);
}
26 changes: 21 additions & 5 deletions test/RelayRouter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ describe('useRelay', () => {
});

describe('kitchen sink', () => {
const WidgetRoot = ({ widget, first, second, third, route }) => {
const WidgetRoot = ({ widget, first, second, third, fourth, route }) => {
expect(route).to.be.ok;

return (
<div className={widget.name}>
{first}
{second}
{third}
{fourth}
</div>
);
};
Expand Down Expand Up @@ -62,18 +63,23 @@ describe('useRelay', () => {

const routes = (
<Route
path="/"
path="/:parentName"
component={WidgetRootContainer}
getQueries={() => ({
widget: () => Relay.QL`query { widget }`,
})}
prepareParams={({ parentName, ...params }) => ({
...params,
parentName: `${parentName}-`,
})}
>
<Route
path=":pathName"
components={{
first: WidgetContainer,
second: WidgetContainer,
third: WidgetContainer,
fourth: WidgetContainer,
}}
queries={{
first: {
Expand All @@ -85,6 +91,9 @@ describe('useRelay', () => {
third: {
widget: () => Relay.QL`query { widget }`,
},
fourth: {
widget: () => Relay.QL`query { widgetByArg(name: $parentName) }`,
},
}}
render={{
third: ({ props }) => {
Expand All @@ -96,7 +105,10 @@ describe('useRelay', () => {
return <div className="qux" />;
},
}}
queryParams={['queryName']}
prepareParams={(params, location) => ({
...params,
queryName: location.query.name,
})}
/>
</Route>
);
Expand All @@ -116,7 +128,7 @@ describe('useRelay', () => {
render() {
return (
<Router
history={createMemoryHistory('/bar?queryName=baz')}
history={createMemoryHistory('/parent/bar?name=baz')}
routes={routes}
render={applyRouterMiddleware(useRelay)}
environment={environment}
Expand All @@ -137,12 +149,16 @@ describe('useRelay', () => {
ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'bar');
});

it('should support query params', () => {
it('should support prepared params', () => {
ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'baz');
});

it('should support renderFetched', () => {
ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'qux');
});

it('should support modified parent params', () => {
ReactTestUtils.findRenderedDOMComponentWithClass(instance, 'parent-');
});
});
});

0 comments on commit 91884b6

Please sign in to comment.