Pagination
Every list endpoint — feeds, followers/following, reactions, notifications — pages with
an opaque keyset cursor, never OFFSET. The cursor encodes a position on
(activity_time DESC, activity_id DESC) (or the equivalent ordering column for
followers/reactions/notifications), so pages stay correct even as new rows are inserted
ahead of where you’re reading — an OFFSET-based page would skip or repeat rows under
concurrent writes. Treat the cursor as opaque: don’t parse it, just pass back whatever
the previous page returned as next.
First page
Section titled “First page”const page = await client.feed('user', 'maya').get({ limit: 20 })page.results // Activity[]page.next // string | null — opaque cursor, or null when there's no moreimport { useFeed } from '@dropin/react'
// First page loads automatically on mount.const { activities, hasNext, isLoading } = useFeed('user', 'maya')const page = await server.feed('user', 'maya').get({ limit: 20 })Next page via the next cursor
Section titled “Next page via the next cursor”Pass the previous page’s next back in as next to get the following page. The same
{ limit, next } shape works on every paginated method — feed().get(),
feed().followers()/.following(), reactions.list(), and notifications.get().
let page = await client.feed('user', 'maya').get({ limit: 20 })while (page.next) { page = await client.feed('user', 'maya').get({ limit: 20, next: page.next })}// The hook tracks the cursor for you — just call loadNext() to append the next page.const { activities, hasNext, loadNext, isLoading } = useFeed('user', 'maya')
return hasNext && <button onClick={loadNext} disabled={isLoading}>Load more</button>let page = await server.feed('user', 'maya').get({ limit: 20 })if (page.next) { page = await server.feed('user', 'maya').get({ limit: 20, next: page.next })}See feeds for the full set of feed reads this applies to.