Skip to content

Commit

Permalink
Add prerender hook and extraQuery support
Browse files Browse the repository at this point in the history
  • Loading branch information
taion committed May 22, 2017
1 parent e9e2e6b commit 72af509
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 13 deletions.
10 changes: 10 additions & 0 deletions src/createElements.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,24 @@ export default function createElements(
queryConfigs,
readyStates,
routeRunQueries,
routeExtraData,
) {
return routeMatches.map((match, i) => {
const { route } = match;

const Component = Components[i];
const queryConfig = queryConfigs[i];
const readyState = readyStates[i];
const extraData = routeExtraData[i];

const isComponentResolved = isResolved(Component);

// Handle non-Relay routes.
if (!queryConfig) {
if (route.prerender) {
route.prerender({ ...readyState, match, extraData });
}

if (route.render) {
return route.render({
match,
Expand All @@ -37,6 +43,10 @@ export default function createElements(
return Component ? <Component {...match} /> : null;
}

if (route.prerender) {
route.prerender({ ...readyState, match, extraData });
}

if (!isComponentResolved) {
// Can't render a RelayReadyStateRenderer here.
if (route.render) {
Expand Down
83 changes: 70 additions & 13 deletions src/createResolveElements.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import checkRelayQueryData from 'react-relay/lib/checkRelayQueryData';

import createElements from './createElements';

const { hasOwnProperty } = Object.prototype;

// TODO: Should we disable Relay query caching for SSR? If so, we should cache
// query sets ourselves.

Expand Down Expand Up @@ -44,6 +46,11 @@ export default function createResolveElements(environment) {
route => route.getQueries,
route => route.queries,
);
const extraQueryNodes = getRouteValues(
routeMatches,
route => route.getExtraQuery,
route => route.extraQuery,
);
const forceFetches = getRouteValues(
routeMatches,
route => route.getForceFetch,
Expand All @@ -52,7 +59,7 @@ export default function createResolveElements(environment) {

let params = null;

const queryConfigs = routeMatches.map((routeMatch, i) => {
const routeParams = routeMatches.map((routeMatch) => {
const { route } = routeMatch;

// We need to always run this to make sure we don't miss params.
Expand All @@ -61,13 +68,27 @@ export default function createResolveElements(environment) {
params = route.prepareParams(params, routeMatch);
}

const queries = matchQueries[i];
return params;
});

const queryConfigs = matchQueries.map((queries, i) => {
if (!queries) {
return null;
}

const name = `__route_${i}_${routeIndices[i]}`;
return { name, queries, params };
return {
name: `__route_${i}_${routeIndices[i]}`,
queries,
params: routeParams[i],
};
});

const extraQueries = extraQueryNodes.map((extraQueryNode, i) => {
if (!extraQueryNode) {
return null;
}

return Relay.createQuery(extraQueryNode, routeParams[i]);
});

const earlyComponents = Components.some(isPromise) ?
Expand All @@ -77,7 +98,9 @@ export default function createResolveElements(environment) {

const earlyReadyStates = earlyComponents.map((Component, i) => {
const queryConfig = queryConfigs[i];
if (!queryConfig) {
const extraQuery = extraQueries[i];

if (!queryConfig && !extraQuery) {
return null;
}

Expand All @@ -90,18 +113,29 @@ export default function createResolveElements(environment) {
// requests. We can send out requests for resolved components, but that
// runs the risk of the data we request now being out-of-sync with the
// data we request later.
const querySet = Relay.getQueries(Component, queryConfig);
const hasQueryData = Object.values(querySet).every(query => (
!query || checkRelayQueryData(recordStore, query)
));
if (queryConfig) {
const querySet = Relay.getQueries(Component, queryConfig);
const hasQueryData = Object.values(querySet).every(query => (
!query || checkRelayQueryData(recordStore, query)
));

if (!hasQueryData) {
if (!hasQueryData) {
return PENDING_READY_STATE;
}
}

if (extraQuery && !checkRelayQueryData(recordStore, extraQuery)) {
return PENDING_READY_STATE;
}

return forceFetches[i] ? STALE_READY_STATE : DONE_READY_STATE;
});

const earlyRouteExtraData = extraQueries.map((extraQuery, i) => (
extraQuery && earlyReadyStates[i].ready ?
environment.readQuery(extraQuery)[0] : null
));

if (earlyReadyStates.some(readyState => readyState && !readyState.done)) {
yield createElements(
environment,
Expand All @@ -110,6 +144,7 @@ export default function createResolveElements(environment) {
queryConfigs,
earlyReadyStates,
null, // No retry here, as these will never be in error.
earlyRouteExtraData,
);
}

Expand All @@ -118,13 +153,29 @@ export default function createResolveElements(environment) {

const routeRunQueries = fetchedComponents.map((Component, i) => {
const queryConfig = queryConfigs[i];
if (!queryConfig) {
const extraQuery = extraQueries[i];

if (!queryConfig && !extraQuery) {
return null;
}

return function runQueries(onReadyStateChange) {
const querySet = Relay.getQueries(Component, queryConfig);
let querySet;
if (queryConfig) {
querySet = Relay.getQueries(Component, queryConfig);
}

if (extraQuery) {
let extraQueryKey = '__extra';
while (hasOwnProperty.call(querySet, extraQueryKey)) {
extraQueryKey = `_${extraQueryKey}`;
}

// Relay caches query sets, so it's very important to not modify the
// query set in-place.
querySet = { ...querySet, [extraQueryKey]: extraQuery };
}

return function runQueries(onReadyStateChange) {
return forceFetches[i] ?
environment.forceFetch(querySet, onReadyStateChange) :
environment.primeCache(querySet, onReadyStateChange);
Expand All @@ -148,13 +199,19 @@ export default function createResolveElements(environment) {
},
));

const routeExtraData = extraQueries.map((extraQuery, i) => (
extraQuery && fetchedReadyStates[i].ready ?
environment.readQuery(extraQuery)[0] : null
));

yield createElements(
environment,
routeMatches,
fetchedComponents,
queryConfigs,
fetchedReadyStates,
routeRunQueries,
routeExtraData,
);
};
}

0 comments on commit 72af509

Please sign in to comment.