Does nested pagination with relayStylePagination work?
For instance, my website is loads comments (paginated), and then replies on each comment (also paginated).
Can I use the native relayStylePagination here?
Or would I need to modify it?
watson
February 1, 2023, 6:57pm
2
What version of @apollo/client
are you using? There was a regression reported that some community members mentioned nested pagination not working, but working after the fix in @apollo/client@3.4.7
opened 10:11AM - 06 Aug 21 UTC
closed 10:32PM - 09 Aug 21 UTC
🐞 bug
has-reproduction
shipped
🧩 implementation-detail
📟 regression
💸 caching
**Intended outcome:**
The 3.4.* versions introduce a regression on the `merge` … policy
**Actual outcome:**
The merge custom policy should receive correct parameters
**How to reproduce the issue:**
Here a unit test:
```typescript
import { gql, InMemoryCache, useQuery } from '@apollo/client'
import { MockedProvider } from '@apollo/client/testing'
import { render, screen, waitFor } from '@testing-library/react'
import faker from 'faker'
const cache = new InMemoryCache({
typePolicies: {
Country: {
fields: {
cities: {
keyArgs: ['size'],
merge(existing, incoming, { args }) {
console.log(existing, incoming, { args })
if (!args) return incoming
const items = existing ? existing.slice(0) : []
const offset = args.offset ?? 0
for (let i = 0; i < incoming.length; ++i) {
items[offset + i] = incoming[i]
}
return items
},
},
},
},
CityInfo: {
merge: true,
},
},
})
const GET_COUNTRIES = gql`
query GetCountries {
countries {
id
...WithSmallCities
...WithAirQuality
}
}
fragment WithSmallCities on Country {
biggestCity {
id
}
smallCities: cities(size: SMALL) {
id
}
}
fragment WithAirQuality on Country {
biggestCity {
id
info {
airQuality
}
}
}
`
function Test() {
const { data } = useQuery(GET_COUNTRIES)
return <div data-testid="countryNumber">{data?.countries.length}</div>
}
it('should render without error', async () => {
const countries = [
{
__typename: 'Country',
id: faker.datatype.uuid(),
biggestCity: {
__typename: 'City',
id: faker.datatype.uuid(),
info: {
__typename: 'CityInfo',
airQuality: faker.datatype.number(),
},
},
smallCities: [
{
__typename: 'City',
id: faker.datatype.uuid(),
},
],
},
]
const mock = { request: { query: GET_COUNTRIES }, result: { data: { countries } } }
render(
<MockedProvider cache={cache} mocks={[mock]} resolvers={{}}>
<Test />
</MockedProvider>,
)
await waitFor(() => {
const element = screen.getByTestId('countryNumber')
expect(element).toHaveTextContent(countries.length.toString())
})
})
```
If you try to run this test, you will have this error `Uncaught [TypeError: existing.slice is not a function]`, since we receive these arguments into the merge function:
`{ __ref: 'City:a44cfd2e-c50f-4fcf-924d-d8e275c8df07' }` as existing
`{
id: 'a44cfd2e-c50f-4fcf-924d-d8e275c8df07',
__typename: 'City',
info: {
__typename: 'CityInfo',
airQuality: 20807
}
}` as incoming
We should have:
`undefined` as existing
`{ __ref: 'City:a44cfd2e-c50f-4fcf-924d-d8e275c8df07' }` as incoming
FYI If we delete `CityInfo: { merge: true }` from the cache configuration, it works.
**Versions**
It works with 3.3.21 but not with the new 3.4.* versions