I’m using react, graphql, and apollo. I’ve implemented a server side paginated table. The problem is that when I page forward, and the new items come in from the network request (correctly) they are rendered as appended to the existing items in the table.
The behavior I expect would be that the newly fetched items only are rendered, and then if I page back again the original items should be displayed (from the cache).
Now, reading the apollo docs on this matter I see that this is standard behavior I guess. From the docs: "Once the new data is returned from the server, the updateQuery function is used to merge it with the existing data, which will cause a re-render of your UI component with an expanded list."
But I have not been able to find a way to implement the behavior I want (which is an extremely common pagination pattern)
Here is the code I have:
const [page, setPage] = useState<number>(0);
const [sortField, setSortField] = useState('name');
const [sortOrder, setSortOrder] = useState<Order>('ASC');
const [sortModel, setSortModel] = useState<GridSortModel>([
{ field: 'name', sort: 'asc' },
]);
const { data } = useQuery(Document, {
variables: {
id,,
input: {
count: 25,
page: page + 1,
sort: sortField,
order: sortOrder,
},
},
notifyOnNetworkStatusChange: true,
fetchPolicy: 'cache-first',
});
const handleSortModelChange = useCallback((model: GridSortModel) => {
const { field = 'name', sort = 'ASC' } = model[0] || {};
const order = sort?.toUpperCase() as Order;
setSortModel(model);
setSortField(field);
setSortOrder(order);
}, []);
const handlePageChange = useCallback((newPage: number) => {
setPage(newPage);
}, []);
I have verified that it is not an issue with the table implementation or other UI code by rendering the raw data and inspecting the results when I paginate
2
Answers
I am not happy with the solution I had to implement and will therefore post a bounty for this when I am able even though I ended up solving this in what I think was a non-optimal way myself. I had to add a custom merge function in the typePolicies for the field on which the pagination was being performed. The code is as follows:
And in my query:
fetchPolicy: 'cache-first',
That said, it seems strange that I needed to make a custom merge function in my typePolicies config in order to get Apollo to handle such a common use case (server pagination without lazy load and server sort). If anyone knows an easier way I'd love to be enlightened in a comment or another solution.
You can use the the
fetchMore
function is used to fetch additional data without merging it with the existing data. TheupdateQuery
function is set to(prev, { fetchMoreResult }) => fetchMoreResult
to replace the existing data with the newly fetched data.Let me know if this works.