Client Hooks API Reference
Blocksweb provides a comprehensive set of React hooks for fetching and managing data in your components.
Overview
All hooks are imported from @blocksweb/core/client:
import {
usePage,
usePages,
useCollection,
useCollectionRecord,
useAsset,
useBlocks,
} from "@blocksweb/core/client";Page Hooks
usePage
Fetch a single page by slug or ID.
function usePage(slug: string): UseQueryResult<Page>;Example:
import { usePage } from '@blocksweb/core/client';
function PageComponent({ slug }: { slug: string }) {
const { data: page, isLoading, error } = usePage(slug);
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error loading page</div>;
return (
<div>
<h1>{page.name}</h1>
<p>{page.description}</p>
</div>
);
}Returns:
{
data?: {
id: string;
name: string;
slug: string;
description?: string;
blocks: Block[];
metadata: PageMetadata;
status: 'draft' | 'published';
createdAt: Date;
updatedAt: Date;
};
isLoading: boolean;
error: Error | null;
refetch: () => void;
}usePages
Fetch multiple pages with optional filtering.
function usePages(options?: PageQueryOptions): UseQueryResult<Page[]>;Options:
type PageQueryOptions = {
status?: "draft" | "published" | "all";
limit?: number;
offset?: number;
sort?: "name" | "createdAt" | "updatedAt";
order?: "asc" | "desc";
};Example:
const { data: pages } = usePages({
status: "published",
limit: 10,
sort: "createdAt",
order: "desc",
});usePublishedPages
Fetch all published pages (convenience wrapper).
function usePublishedPages(): UseQueryResult<Page[]>;Example:
const { data: publishedPages } = usePublishedPages();
return (
<nav>
{publishedPages?.map(page => (
<a key={page.id} href={page.slug}>{page.name}</a>
))}
</nav>
);Collection Hooks
useCollection
Query a collection with filtering, sorting, and pagination.
function useCollection<T>(
collectionName: string,
query?: CollectionQuery
): UseQueryResult<T[]>;Query Options:
type CollectionQuery = {
where?: Record<string, any>;
limit?: number;
offset?: number;
sort?: string;
order?: "asc" | "desc";
};Example:
const { data: products } = useCollection("products", {
where: { category: "electronics", inStock: true },
limit: 20,
sort: "price",
order: "asc",
});useCollectionRecord
Fetch a single record by ID.
function useCollectionRecord<T>(
collectionName: string,
recordId: string
): UseQueryResult<T>;Example:
const { data: product } = useCollectionRecord('products', productId);
return (
<div>
<h2>{product?.name}</h2>
<p>${product?.price}</p>
</div>
);useCollectionRecords
Fetch multiple records by IDs.
function useCollectionRecords<T>(
collectionName: string,
recordIds: string[]
): UseQueryResult<T[]>;Example:
const { data: products } = useCollectionRecords("products", [
"prod_1",
"prod_2",
"prod_3",
]);useInfiniteCollection
Infinite scroll pagination for collections.
function useInfiniteCollection<T>(
collectionName: string,
query?: CollectionQuery
): UseInfiniteQueryResult<T[]>;Example:
const {
data,
fetchNextPage,
hasNextPage,
isFetchingNextPage
} = useInfiniteCollection('blog', {
limit: 10
});
return (
<div>
{data?.pages.map(page =>
page.map(post => <BlogPost key={post.id} {...post} />)
)}
{hasNextPage && (
<button onClick={() => fetchNextPage()} disabled={isFetchingNextPage}>
{isFetchingNextPage ? 'Loading...' : 'Load More'}
</button>
)}
</div>
);useCollectionSearch
Full-text search across collection records.
function useCollectionSearch<T>(
collectionName: string,
searchTerm: string,
options?: SearchOptions
): UseQueryResult<T[]>;Example:
const [search, setSearch] = useState('');
const { data: results } = useCollectionSearch('products', search, {
fields: ['name', 'description'],
limit: 10
});
return (
<>
<input value={search} onChange={e => setSearch(e.target.value)} />
{results?.map(product => <ProductCard key={product.id} {...product} />)}
</>
);Asset Hooks
useAsset
Fetch a single asset by ID.
function useAsset(assetId: string): UseQueryResult<Asset>;Example:
const { data: asset } = useAsset(assetId);
return (
<img
src={asset?.url}
alt={asset?.name}
width={asset?.width}
height={asset?.height}
/>
);Asset Type:
type Asset = {
id: string;
name: string;
filename: string;
url: string;
mimeType: string;
size: number;
width?: number;
height?: number;
createdAt: Date;
};useAssets
Fetch multiple assets with filtering.
function useAssets(options?: AssetQueryOptions): UseQueryResult<Asset[]>;Example:
const { data: images } = useAssets({
mimeType: "image/*",
limit: 50,
});useAssetsByIds
Fetch specific assets by their IDs.
function useAssetsByIds(assetIds: string[]): UseQueryResult<Asset[]>;Mutation Hooks
useCreateRecord
Create a new record in a collection.
function useCreateRecord<T>(
collectionName: string
): UseMutationResult<T, Error, Partial<T>>;Example:
const createProduct = useCreateRecord("products");
const handleSubmit = async (data) => {
try {
const newProduct = await createProduct.mutateAsync(data);
console.log("Created:", newProduct);
} catch (error) {
console.error("Failed:", error);
}
};useUpdateRecord
Update an existing record.
function useUpdateRecord<T>(
collectionName: string,
recordId: string
): UseMutationResult<T, Error, Partial<T>>;Example:
const updateProduct = useUpdateRecord("products", productId);
const handleUpdate = async (updates) => {
await updateProduct.mutateAsync(updates);
};useDeleteRecord
Delete a record.
function useDeleteRecord(
collectionName: string,
recordId: string
): UseMutationResult<void, Error>;Example:
const deleteProduct = useDeleteRecord("products", productId);
const handleDelete = async () => {
if (confirm("Are you sure?")) {
await deleteProduct.mutateAsync();
}
};Editor Hooks
These hooks are only available within the Blocksweb editor.
useBlocks
Manage blocks on the current page.
function useBlocks(): {
blocks: Block[];
addBlock: (block: Block) => void;
updateBlock: (id: string, updates: Partial<Block>) => void;
deleteBlock: (id: string) => void;
reorderBlocks: (ids: string[]) => void;
selectedBlockId: string | null;
selectBlock: (id: string | null) => void;
};Example:
const { blocks, addBlock, deleteBlock, selectedBlockId } = useBlocks();
const handleAddHero = () => {
addBlock({
type: "Hero",
props: {
title: "New Hero",
subtitle: "Subtitle here",
},
});
};useBlock
Get the current block context (must be used within a Blocksweb component).
function useBlock(): Block | null;Example:
const MyComponent: IBlockswebComponent = () => {
const block = useBlock();
return <div data-block-id={block?.id}>...</div>;
};usePageData
Access current page data and metadata.
function usePageData(): {
page: Page;
locale: string;
setLocale: (locale: string) => void;
metadata: PageMetadata;
updateMetadata: (updates: Partial<PageMetadata>) => void;
};useAutoSave
Monitor auto-save status.
function useAutoSave(): {
isSaving: boolean;
lastSaved: Date | null;
error: Error | null;
};Example:
const { isSaving, lastSaved } = useAutoSave();
return (
<div className="editor-status">
{isSaving ? 'Saving...' : `Last saved: ${lastSaved?.toLocaleTimeString()}`}
</div>
);Context Hooks
useBlocksweb
Access global Blocksweb settings and configuration.
function useBlocksweb(): {
settings: BlockswebSettings;
isEditor: boolean;
isPreview: boolean;
apiKey: string;
workspaceId: string;
};Hook Options
Most hooks use React Query under the hood and support these options:
{
enabled?: boolean; // Whether to run the query
refetchInterval?: number; // Auto-refetch interval (ms)
refetchOnWindowFocus?: boolean;
staleTime?: number; // How long data stays fresh (ms)
cacheTime?: number; // How long to cache (ms)
onSuccess?: (data) => void;
onError?: (error) => void;
}Example:
const { data } = useCollection("products", query, {
enabled: isLoggedIn, // Only fetch if logged in
refetchInterval: 30000, // Refetch every 30 seconds
staleTime: 5 * 60 * 1000, // Consider fresh for 5 minutes
onSuccess: (data) => {
console.log("Fetched:", data.length, "products");
},
});Error Handling
All hooks return error information:
const { data, error, isLoading, isError } = usePage(slug);
if (isError) {
return <ErrorDisplay error={error} />;
}Common error types:
type BlockswebError = {
message: string;
code: "NOT_FOUND" | "UNAUTHORIZED" | "NETWORK_ERROR" | "SERVER_ERROR";
status?: number;
};Optimistic Updates
For mutations, use optimistic updates:
const updateProduct = useUpdateRecord("products", productId);
const handleUpdate = async (updates) => {
await updateProduct.mutateAsync(updates, {
onMutate: async (newData) => {
// Optimistically update the UI
await queryClient.cancelQueries(["products", productId]);
const previousData = queryClient.getQueryData(["products", productId]);
queryClient.setQueryData(["products", productId], newData);
return { previousData };
},
onError: (err, newData, context) => {
// Revert on error
queryClient.setQueryData(["products", productId], context?.previousData);
},
});
};TypeScript Usage
All hooks are fully typed. Provide generic types for type safety:
type Product = {
id: string;
name: string;
price: number;
inStock: boolean;
};
const { data: products } = useCollection<Product>("products");
// `products` is typed as Product[]
const { data: product } = useCollectionRecord<Product>("products", id);
// `product` is typed as ProductNext Steps
- Configuration - Configure Blocksweb settings
- Collections Overview - Work with structured data
- Collection Providers - Setup data sources