add useEntitiesPublicInfinite hook - #552
Conversation
063ba61 to
68f1d5f
Compare
There was a problem hiding this comment.
Pull Request Overview
This PR adds a new useEntitiesPublicInfinite hook to enable infinite scroll/pagination for public entities using TanStack Query's infinite query capabilities. The implementation follows the existing pattern of public entity queries but adds support for pagination through getNextPageParam.
- Introduces
useEntitiesPublicInfinitehook for infinite pagination of public entities - Updates
QueryPublicParamstype to makeenabledparameter optional - Adds example implementation demonstrating infinite query usage with podcasts
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
packages/hypergraph-react/src/internal/types.ts |
Makes the enabled parameter optional in QueryPublicParams to align with typical React Query patterns |
packages/hypergraph-react/src/index.ts |
Exports the new useEntitiesPublicInfinite hook |
packages/hypergraph-react/src/hooks/use-entities-public-infinite.ts |
Implements the new infinite query hook using TanStack Query's useInfiniteQuery |
apps/events/src/routes/podcasts.lazy.tsx |
Increases the fetch limit from 6 to 100 and removes explicit offset parameter |
apps/events/src/routes/podcasts-infinite.lazy.tsx |
Demo component showcasing the new infinite query hook with automatic pagination |
apps/events/src/routes/__root.tsx |
Adds navigation link to the new podcasts infinite query demo page |
apps/events/src/routeTree.gen.ts |
Auto-generated route tree updates for the new demo route |
.changeset/beige-lemons-beg.md |
Documents the patch-level change for the hypergraph-react package |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "@graphprotocol/hypergraph-react": patch | ||
| --- | ||
|
|
||
| add useEntitiesPublicInfinite hook] |
There was a problem hiding this comment.
The changeset description has a typo - there's an extra closing bracket ] at the end of "add useEntitiesPublicInfinite hook]".
| add useEntitiesPublicInfinite hook] | |
| add useEntitiesPublicInfinite hook |
| getNextPageParam: (_lastPage, pages) => { | ||
| return offset + pages.length * first; |
There was a problem hiding this comment.
The getNextPageParam implementation has a bug. It calculates the next offset as offset + pages.length * first, but this doesn't account for the initial offset correctly when paginating.
For example:
- If
offset = 0andfirst = 2, after fetching page 1 (pages.length = 1), the next offset would be0 + 1 * 2 = 2✓ - But if
offset = 10andfirst = 2, after fetching page 1, the next offset would be10 + 1 * 2 = 12, which skips records 10-11
The calculation should be based on the initial page param, not the initial offset. Consider: pageParam + first or track cumulative records fetched.
| setTimeout(() => { | ||
| fetchNextPage(); | ||
| setTimeout(() => { | ||
| fetchNextPage(); | ||
| }, 1000); | ||
| }, 1000); | ||
| }, [fetchNextPage]); |
There was a problem hiding this comment.
The useEffect hook with fetchNextPage in the dependency array will cause an infinite loop or unexpected behavior. The fetchNextPage function reference can change between renders, causing the effect to re-run repeatedly.
This implementation also lacks proper cleanup - if the component unmounts before the timeouts complete, they will still execute.
For demo purposes, consider adding a button to trigger pagination manually, or add proper guards and cleanup:
useEffect(() => {
let cancelled = false;
const timer1 = setTimeout(() => {
if (!cancelled) fetchNextPage();
const timer2 = setTimeout(() => {
if (!cancelled) fetchNextPage();
}, 1000);
}, 1000);
return () => {
cancelled = true;
clearTimeout(timer1);
};
}, []); // Empty dependency array| setTimeout(() => { | |
| fetchNextPage(); | |
| setTimeout(() => { | |
| fetchNextPage(); | |
| }, 1000); | |
| }, 1000); | |
| }, [fetchNextPage]); | |
| const timer1 = setTimeout(() => { | |
| fetchNextPage(); | |
| const timer2 = setTimeout(() => { | |
| fetchNextPage(); | |
| }, 1000); | |
| }, 1000); | |
| return () => { | |
| clearTimeout(timer1); | |
| }; | |
| }, []); |
| mode: 'public', | ||
| first: 6, | ||
| offset: 0, | ||
| first: 100, |
There was a problem hiding this comment.
The offset parameter has been removed. If pagination was previously being used with this component, removing offset: 0 without adding corresponding pagination logic could be a breaking change. Consider whether this removal is intentional or if pagination should be maintained.
| typeIds, | ||
| relationTypeIds.level1, | ||
| relationTypeIds.level2, | ||
| filter, |
There was a problem hiding this comment.
The queryKey is missing the first parameter, which affects query caching. If the same query is made with different first values, they will share the same cache key and return incorrect results.
The queryKey should include first to ensure proper cache isolation:
queryKey: [
'hypergraph-public-entities',
space,
typeIds,
relationTypeIds.level1,
relationTypeIds.level2,
filter,
first, // Add this
'infinite',
],| filter, | |
| filter, | |
| first, |
No description provided.