Hooks Overview
The three core hooks
Section titled “The three core hooks”| Hook | When to use it | Returns |
|---|---|---|
useQuery | List or find nodes. Read-only. | { data, loading, error, reload } |
useMutate | Create, update, delete nodes. | { create, update, remove, restore, mutate } |
useNode | Edit a single node with collaborative rich text. | { data, doc, update, syncStatus, presence, ... } |
When to use which
Section titled “When to use which”- Listing data (tables, lists, grids, search results) —
useQuery - Reading a single node by ID (detail views, cards) —
useQuery(schema, id) - Creating or deleting —
useMutate - Updating properties on a detail page —
useMutate().updateoruseNode().update - Rich text editing (TipTap, collaborative docs) —
useNode(gives you aY.Doc) - Showing who’s online (presence, cursors) —
useNode(gives youpresenceandawareness)
The decision tree
Section titled “The decision tree”Do you need a Yjs document (rich text, canvas)? ├── Yes → useNode └── No ├── Reading data? → useQuery └── Writing data? → useMutateuseNode is the only hook that manages a Yjs document and P2P sync connection. If you don’t need collaborative editing, useQuery + useMutate are simpler and more efficient.
Supporting hooks
Section titled “Supporting hooks”| Hook | Purpose |
|---|---|
useIdentity | Get the current user’s DID and auth status |
useCan / useGrants | Permission checks and grant management — see the Authorization guide |
useComments | Thread-based comments on any node |
useHistory | Change history for a node |
useUndo | Undo/redo for node changes |
All hooks require XNetProvider
Section titled “All hooks require XNetProvider”Every hook reads from a React context provided by XNetProvider. If you call a hook outside the provider, it throws:
import { XNetProvider } from '@xnetjs/react'import { XNetDevToolsProvider } from '@xnetjs/devtools'
function App() { return ( <XNetProvider config={{ authorDID, signingKey }}> <XNetDevToolsProvider> {/* All hooks work inside here */} <TaskList /> </XNetDevToolsProvider> </XNetProvider> )}Data flow
Section titled “Data flow”React Component │ ├── useQuery(TaskSchema, filter) │ └── NodeStore.list() → SQLite │ └── subscribes to NodeChangeEvents │ ├── useMutate() │ └── NodeStore.create/update/delete() │ ├── validates against schema │ ├── signs change (Ed25519) │ ├── persists to SQLite │ ├── emits NodeChangeEvent → useQuery re-renders │ └── syncs to peers (via SyncManager) │ └── useNode(PageSchema, id) ├── NodeStore (structured properties) └── Y.Doc (rich text) ├── WebRTC sync (via SyncManager or WebSocketSyncProvider) ├── debounced persistence to SQLite └── awareness (presence, cursors)Next steps
Section titled “Next steps” useQuery Read data reactively. Filter, sort, paginate.
useMutate Create, update, delete with type safety.
useNode Collaborative editing with Yjs, presence, and sync.
Your own server Run @xnetjs/server with your own auth instead of a managed Hub.