useQuery
Quick example
Section titled “Quick example”import { useQuery } from '@xnet/react'import { TaskSchema } from './schema'
function TaskList() { const { data: tasks, loading } = useQuery(TaskSchema, { where: { status: 'todo' }, orderBy: { createdAt: 'desc' }, limit: 20 })
if (loading) return <p>Loading...</p> return ( <ul> {tasks.map((t) => ( <li key={t.id}>{t.title}</li> ))} </ul> )}Signature
Section titled “Signature”useQuery has three overloads:
// Overload 1: List all nodes of a schemafunction useQuery<P>(schema: DefinedSchema<P>): QueryListResult<P>
// Overload 2: Get a single node by IDfunction useQuery<P>(schema: DefinedSchema<P>, id: string): QuerySingleResult<P>
// Overload 3: Query with filtersfunction useQuery<P>(schema: DefinedSchema<P>, filter: QueryFilter<P>): QueryListResult<P>The second argument determines the overload: pass a string for single-node lookup, an object for filtered queries, or omit it to get all nodes.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
schema | DefinedSchema<P> | The schema to query. Created with defineSchema(). |
id | string | (Overload 2) Node ID to fetch. |
filter | QueryFilter<P> | (Overload 3) Filter, sort, and pagination options. |
QueryFilter
Section titled “QueryFilter”| Field | Type | Default | Description |
|---|---|---|---|
where | Partial<InferCreateProps<P>> | — | Filter by property values. Strict equality matching. |
includeDeleted | boolean | false | Include soft-deleted nodes in results. |
orderBy | Record<string, 'asc' | 'desc'> | — | Sort by any property, createdAt, or updatedAt. |
limit | number | — | Maximum results to return. |
offset | number | — | Skip N results (for pagination). |
Return value
Section titled “Return value”List result (overloads 1 and 3)
Section titled “List result (overloads 1 and 3)”| Field | Type | Description |
|---|---|---|
data | FlatNode<P>[] | The query results. Properties are spread to top level. |
loading | boolean | true during initial load, false once data is available. |
error | Error | null | Any error during query execution. |
reload | () => Promise<void> | Force re-fetch from store. Rarely needed — data auto-updates. |
Single result (overload 2)
Section titled “Single result (overload 2)”| Field | Type | Description |
|---|---|---|
data | FlatNode<P> | null | The node, or null if not found or deleted. |
loading | boolean | true during initial load. |
error | Error | null | Any error during query execution. |
reload | () => Promise<void> | Force re-fetch from store. |
FlatNode
Section titled “FlatNode”Every node includes system fields (managed automatically) plus your schema properties:
interface FlatNode<P> { id: string schemaId: string // e.g., 'xnet://my-app/Task' createdAt: number // Auto-set at creation time createdBy: string // DID of creator updatedAt: number // Auto-updated on every change updatedBy: string // DID of last modifier deleted: boolean // ... plus all your schema properties}You can filter and sort by any of these system fields without defining them in your schema.
Usage patterns
Section titled “Usage patterns”List all nodes
Section titled “List all nodes”The simplest query — returns every node of a schema:
const { data: tasks } = useQuery(TaskSchema)// tasks: FlatNode<typeof TaskSchema._properties>[]Filter and sort
Section titled “Filter and sort”const { data: activeTasks } = useQuery(TaskSchema, { where: { status: 'doing' }, orderBy: { updatedAt: 'desc' }, limit: 50})Single node by ID
Section titled “Single node by ID”const { data: task } = useQuery(TaskSchema, taskId)// task: FlatNode | nullConditional query (skip when ID is null)
Section titled “Conditional query (skip when ID is null)”When id is null or undefined, use a guard:
function TaskDetail({ id }: { id: string | null }) { // Only query when id is available const { data: task } = useQuery(TaskSchema, id ?? '')
if (!id || !task) return <p>No task selected</p> return <h1>{task.title}</h1>}Pagination
Section titled “Pagination”const [page, setPage] = useState(0)const PAGE_SIZE = 20
const { data: tasks } = useQuery(TaskSchema, { orderBy: { createdAt: 'desc' }, limit: PAGE_SIZE, offset: page * PAGE_SIZE})Gotchas
Section titled “Gotchas”Related
Section titled “Related”useMutate— write data thatuseQueryreadsuseNode— when you need a Yjs document for one nodedefineSchema— define the schemas you query