Querying Data
Fetch data in Server Components with the server client or in Client Components with React Query hooks. Both use the same select and filter API.
Server Components
List entities
app/projects/page.tsx
1
2
3
4
5
6
7
import { pylo } from '@/lib/pylo';
const { data, pagination } = await pylo.project.list({ select: { id: true, name: true, created_at:
true, }, pagination: { page: 1, per_page: 20 }, });
// data: Array<{ id: string; name: string | null; created_at: string }> // pagination: { total,
current_page, per_page, last_page, has_more_pages }If you omit select, all scalar fields are returned.
Fetch by ID
example.ts
1
2
3
4
5
6
7
8
9
10
11
const project = await pylo.project.byId('project-uuid', {
select: {
id: true,
name: true,
customer: {
select: { id: true, name: true },
},
},
});
// Returns null if not foundClient Components (React Query Hooks)
usePyloList
components/project-list.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
'use client';
import { pylo } from "@/lib/pylo-hooks";
export function ProjectList() {
const { data, pagination, isLoading, error } = pylo.usePyloList('project', {
select: { id: true, name: true, created_at: true },
pagination: { page: 1, per_page: 20 },
filter: {
sortby: [{ field: 'created_at', order: 'desc' }],
},
});
if (isLoading) return <div>Loading...</div>; if (error) return <div>Error: {error.message}</div>;
return ( <div> {data?.map((project) => ( <div key={project.id}>{project.name}</div> ))} <p>Page
{pagination?.current_page} of {pagination?.last_page}</p> </div> ); }| Field | Type | Description |
|---|---|---|
data | T[] | undefined | Array of entities matching the select |
pagination | PaginationData | undefined | Pagination metadata |
isLoading | boolean | True while the initial request is loading |
error | Error | null | Error if the request failed |
refetch | () => void | Manually trigger a refetch |
usePyloById
Fetch a single entity by ID. Automatically disabled when id is null or undefined.
components/project-detail.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'use client';
import { pylo } from "@/lib/pylo-hooks";
export function ProjectDetail({ projectId }: { projectId: string }) {
const { data: project, isLoading } = pylo.usePyloById('project', projectId, {
select: {
id: true,
name: true,
customer: { select: { id: true, name: true } },
},
});
if (isLoading) return <div>Loading...</div>; if (!project) return <div>Not found</div>;
return ( <div> <h1>{project.name}</h1> <p>Customer: {project.customer?.data.name}</p> </div> ); }usePyloInfiniteList
Infinite scrolling with automatic page management, built on useInfiniteQuery.
components/infinite-list.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
'use client';
import { pylo } from "@/lib/pylo-hooks";
export function InfiniteProjectList() {
const {
data,
fetchNextPage,
hasNextPage,
isFetchingNextPage,
isLoading,
} = pylo.usePyloInfiniteList('project', {
perPage: 20,
select: { id: true, name: true },
filter: {
sortby: [{ field: 'created_at', order: 'desc' }],
},
});
if (isLoading) return <div>Loading...</div>;
return ( <div> {data?.data.map((project) => ( <div key={project.id}>{project.name}</div> ))}
{hasNextPage && ( <button onClick={() => fetchNextPage()} disabled={isFetchingNextPage}>
{isFetchingNextPage ? 'Loading...' : 'Load more'} </button> )} </div> ); }Select
The select object determines which fields are returned. Only fields set to true are included.
example.ts
1
2
select: { id: true, name: true }
// → { id: string; name: string | null }Omit select entirely to get all scalar fields.
Relations
Include relations by providing a nested select object:
example.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
select: {
id: true,
// hasOne — pick specific fields
customer: {
select: { id: true, name: true },
},
// hasMany — with filter and pagination
invoices: {
select: { id: true, amount_net: true },
pagination: { per_page: 5 },
filter: {
sortby: [{ field: 'created_at', order: 'desc' }],
},
},
}Response shapes:
- hasOne (ManyToOne, OneToOne):
{ data: { ... } } | null - hasMany (OneToMany, ManyToMany):
{ data: [...], pagination: { ... } }
Error Handling
Server client — throws PyloError:
example.ts
1
2
3
4
import { PyloError } from '@pylo/nextjs';
try { const { data } = await pylo.project.list(); } catch (error) { if (error instanceof PyloError)
{ console.error(error.message); console.error(error.graphqlErrors); } }Client hooks — return error state:
example.ts
1
2
const { data, error } = pylo.usePyloList('project', { ... });
if (error) console.error(error.message);