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 | nullExample:
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