Summary: I can't get a total number of records from my GraphQL endpoint. I only know if I have reached the end of my GraphQL records list when I am parsing the response from the endpoint. How can I make my custom pagination component aware that it's on the last page?
Details: I'm using React Admin with AWS AppSync (GraphQL on DynamoDB) using ra-data-graphql
. AppSync can't tell you the total number of records available to a list query, and it also limits the number of records you can return to a 1MB payload. Instead, it includes a nextToken
value if there are more records to query, which you can include in subsequent list queries.
I have created a custom pagination component that only uses "prev" and "next" links, which is fine. But I need to know when the last page is displayed. Right now, I only know this in the parseResponse()
function that I'm passing in to buildQuery()
for the list query. At this point, I have access to the nextToken
value. If it's empty, then I have fetched the last page of results from AppSync. If I could pass this value, or even a boolean e.g. lastPage
to the custom pagination component, I'd be all set. How can I do this in React Admin?
There is also a way to adapt AppSync resolver to work with page
and perPage
native react-admin parameters.
It's a bad practice because query response is limited by 1MB and also full dynamodb query response needs to be parsed and transformed for each page query, however it does the trick.
{
"version" : "2017-02-28",
"operation" : "Query",
"query" : {
"expression": "userId = :userId",
"expressionValues" : {
":userId" : $util.dynamodb.toDynamoDBJson($context.identity.sub)
}
}
}
#set($result = {})
#set($result.items = [])
#set($result.length = $ctx.result.items.size())
#set($start = $ctx.arguments.perPage * ($ctx.arguments.page - 1))
#set($end = $ctx.arguments.perPage * $ctx.arguments.page - 1)
#if($end > $result.length - 1)
#set($end = $result.length - 1)
#end
#if($start <= $result.length - 1 && $start >= 0 )
#set($range = [$start..$end])
#foreach($i in $range)
$util.qr($result.items.add($ctx.result.items[$i]))
#end
#end
$util.toJson($result)
...
const buildQuery = () => (
raFetchType,
resourceName,
params
) => {
if (resourceName === "getUserToDos" && raFetchType === "GET_LIST") {
return {
query: gql`
query getUserToDos($perPage: Int!, $page: Int!) {
getUserToDos(perPage: $perPage, page: $page) {
length
items {
todoId
date
...
}
}
}
`,
variables: {
page: params.pagination.page,
perPage: params.pagination.perPage
},
parseResponse: ({ data }) => {
return {
data: data.getUserToDos.items.map(item => {
return { id: item.listingId, ...item };
}),
total: data.getUserToDos.length
};
}
};
}
...