Paginating Next/Previous through a list: able to fetch prepared params before Relay QL Template call?
danmooney opened this issue · 4 comments
I'm having trouble paginating through a list of posts. I'm passing "before" and "after" as query strings with previous and next, respectively. When it's "before", I'd like to use the Relay pagination variables "before" and "last" with the startCursor from pageInfo. When it's "after", I'd like to use the Relay pagination variables "after" and first" with the endCursor from pageInfo. These variable combinations produce the desired normal pagination effect when I inspect in GraphiQL. Is there any way to modify the GraphQL query passed to Relay.QL based on the prepared params from the route? Any insight or feedback on a better implementation would be much appreciated.
My Router:
<Router
history={browserHistory}
render={applyRouterMiddleware(useRelay)}
environment={Relay.Store}
>
<Route
path="/"
component={App}
queries={StoreQueries}
>
<IndexRoute component={PostList} queries={StoreQueries} prepareParams={(params, {location}) => {
let additionalParams = {};
['before', 'after'].forEach((locationQueryParam) => {
if (typeof location.query[locationQueryParam] !== 'undefined') {
additionalParams[locationQueryParam] = location.query[locationQueryParam];
}
});
return {
...params,
...additionalParams,
}
}} />
</Route>
</Router>
My Relay Container:
PostList = Relay.createContainer(PostList, {
initialVariables: {
limit: 10,
after: null,
before: null
},
fragments: {
store: () => {
// can i fetch prepared params here to dynamically alter GraphQL query so I can change the arguments list for allPosts?
return Relay.QL`
fragment on Store {
id
allPosts(first: $limit, after: $after) {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
node {
id
${Post.getFragment('post')}
}
}
}
}
`
}
}
});
I think you just need to add both after: $after
and before: $before
to that query. The null one will just be ignored.
Apologies, I added before: $before
as well as last: $last
. I believe this is still an issue, however. How can one conditionally pass $limit to first
if after
is non-null, or pass $limit to last
if before
is non-null? Do I have to re-evaluate my location params in my fragment before constructing my template literal?
Relay.QL`
fragment on Store {
allPosts(first: $limit, last: $limit, before: $before, after: $after) {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
node {
id
${Post.getFragment('post')}
}
}
}
}
`
You need to set that up in prepareParams
– make it either first
or last
depending on which pagination option is enabled. Or have e.g. a boolean flag for determining which one is relevant.
OK, I got it to work, albeit hackily. Used two separate limit variables in prepareParams
, one for before
and one for after
.
<Router
history={browserHistory}
render={applyRouterMiddleware(useRelay)}
environment={Relay.Store}
>
<Route
path="/"
component={App}
queries={StoreQueries}
>
<IndexRoute component={PostList} queries={StoreQueries} prepareParams={(params, {location}) => {
let additionalParams = {};
['before', 'after'].forEach((locationQueryParam) => {
if (typeof location.query[locationQueryParam] !== 'undefined') {
additionalParams[locationQueryParam] = location.query[locationQueryParam];
}
});
if (additionalParams.before) {
additionalParams.beforeLimit = 10;
} else {
additionalParams.afterLimit = 10;
}
return {
...params,
...additionalParams,
}
}} />
</Route>
</Router>
And my GraphQL signature is as such:
allPosts(first: $afterLimit, last: $beforeLimit, before: $before, after: $after)
Hope this helps someone.