Skip to content

Hooks Reference

Rebase provides React hooks to access framework functionality from any component within the <Rebase> provider tree.

The master hook — access everything:

import { useRebaseContext } from "@rebasepro/core";
function MyComponent() {
const context = useRebaseContext();
context.dataSource // Data operations
context.storageSource // File operations
context.authController // Auth state
context.navigation // Navigation state
context.sideEntityController // Side panel control
context.snackbarController // Toast notifications
}

Access authentication state and capabilities:

import { useAuthController } from "@rebasepro/core";
function UserMenu() {
const auth = useAuthController();
auth.user // Current user (or null)
auth.authLoading // True when auth operation is in progress
auth.initialLoading // Loading initial session on app startup
auth.signOut() // Log out (returns Promise<void>)
auth.getAuthToken() // Get JWT for API calls (returns Promise<string>)
auth.extra // Additional user data (roles, etc.)
auth.capabilities // Capabilities advertised by auth provider (e.g. registration, reset)
}

Fetch and subscribe to a list of entities in a collection. It automatically establishes a real-time WebSocket subscription if supported by the driver, falling back to REST fetches.

import { useCollectionFetch } from "@rebasepro/core";
import { productsCollection } from "../config/collections";
function ProductList() {
const { data, dataLoading, dataLoadingError, noMoreToLoad } = useCollectionFetch({
path: "products",
collection: productsCollection,
itemCount: 20,
filterValues: {
active: ["==", true],
price: [">=", 100]
},
sortBy: ["created_at", "desc"],
searchString: "laptop"
});
if (dataLoading) return <p>Loading products...</p>;
if (dataLoadingError) return <p>Error: {dataLoadingError.message}</p>;
return (
<ul>
{data.map(product => (
<li key={product.id}>{product.values.name} (${product.values.price})</li>
))}
</ul>
);
}
ParameterTypeDescription
pathstringAbsolute collection path (e.g., "products").
collectionEntityCollectionThe collection definition object.
itemCountnumberOptional. Number of entities to fetch.
filterValuesFilterValuesOptional. Query filters. Supports shorthand equality, tuples [op, val], and PostgREST operator strings.
sortBy[string, "asc" | "desc"]Optional. Sort field and order direction tuple.
searchStringstringOptional. Query for full-text search.
PropertyTypeDescription
dataEntity[]Array of fetched entities.
dataLoadingbooleanTrue if the initial load is in progress.
dataLoadingErrorErrorError object if the fetch fails.
noMoreToLoadbooleanTrue if there are no more records beyond the current page/limit.

Fetch and subscribe to a single entity by ID. It renders instantly using cached data if already loaded via a collection fetch, then updates in the background.

import { useEntityFetch } from "@rebasepro/core";
import { productsCollection } from "../config/collections";
function ProductDetail({ productId }) {
const { entity, dataLoading, dataLoadingError } = useEntityFetch({
path: "products",
entityId: productId,
collection: productsCollection
});
if (dataLoading) return <p>Loading product...</p>;
if (dataLoadingError) return <p>Error: {dataLoadingError.message}</p>;
if (!entity) return <p>Product not found</p>;
return (
<div>
<h1>{entity.values.name}</h1>
<p>{entity.values.description}</p>
</div>
);
}
ParameterTypeDescription
pathstringAbsolute collection path.
entityIdstring | numberThe ID of the entity to fetch.
collectionEntityCollectionThe collection definition object.
useCachebooleanOptional. If true and entity is in cache, skips background refresh. (Default: false).

Rebase maintains a global memory cache to prevent UI flashing. You can manipulate this cache directly:

  • populateEntityFetchCache(path, entities): Pre-populates the cache with a list of entities (e.g. after a bulk action or custom API call).
  • clearEntityFetchCache(): Clears the cache. Recommended to call this upon user logout to prevent data leakage.

Hook to evaluate roles and permissions for the current user. It abstracts away the need to manually pass the authController to permission checking functions.

import { usePermissions } from "@rebasepro/core";
import { productsCollection } from "../config/collections";
function CreateProductButton() {
const { canCreate } = usePermissions();
const allowedToCreate = canCreate(productsCollection, "products");
return (
<button disabled={!allowedToCreate}>
Create Product
</button>
);
}
MethodSignatureDescription
canCreate(collection, path) => booleanChecks if the user is allowed to create entities in the collection.
canEdit(collection, path, entity) => booleanChecks if the user is allowed to edit the given entity.
canDelete(collection, path, entity) => booleanChecks if the user is allowed to delete the given entity.
canRead(collection) => booleanChecks if the user is allowed to read the collection.

Utility hook to copy or cut text to the clipboard, with automatic support for fallback mechanisms on older browsers.

[!NOTE] Note the exact spelling of isCoppied (with two ps) in the return payload.

import { useClipboard } from "@rebasepro/core";
function CopyButton({ text }) {
const { copy, isCoppied } = useClipboard({ copiedDuration: 2000 });
return (
<button onClick={() => copy(text)}>
{isCoppied ? "Copied!" : "Copy Text"}
</button>
);
}
OptionTypeDescription
copiedDurationnumberOptional. Time in milliseconds before resetting isCoppied back to false.
onSuccess(text) => voidOptional. Callback triggered on successful copy.
onError(err) => voidOptional. Callback triggered on error.
PropertyTypeDescription
refMutableRefObjectReact ref to attach to input/textarea elements to copy from.
copy(text?: string) => voidTriggers copy of the given text, or the ref element’s content.
cut() => voidTriggers cut of the ref element’s content.
isCoppiedbooleanTrue if text was recently copied.
clipboardstringThe current copied text value.
clearClipboard() => voidClears the clipboard.

Programmatically open entities in a side panel:

import { useSideEntityController } from "@rebasepro/core";
function OpenProductButton({ productId }) {
const sideEntityController = useSideEntityController();
return (
<button onClick={() => {
sideEntityController.open({
path: "products",
entityId: productId,
collection: productsCollection
});
}}>
Open Product
</button>
);
}

Methods:

MethodDescription
open({ path, entityId, collection })Open an entity in a side panel
close()Close the current side panel
replace({ path, entityId, collection })Replace the current side panel content

Show toast notifications:

import { useSnackbarController } from "@rebasepro/core";
function SaveButton() {
const snackbar = useSnackbarController();
const handleSave = async () => {
try {
await saveData();
snackbar.open({ type: "success", message: "Saved successfully!" });
} catch (error) {
snackbar.open({ type: "error", message: "Save failed" });
}
};
}

Access file storage operations:

import { useStorageSource } from "@rebasepro/core";
function FileUploader() {
const storage = useStorageSource();
const upload = async (file: File) => {
const result = await storage.uploadFile({
file,
fileName: file.name,
path: "documents"
});
const url = await storage.getDownloadURL(result.path);
return url;
};
}

Control light/dark theme:

import { useModeController } from "@rebasepro/core";
function ThemeToggle() {
const mode = useModeController();
return (
<button onClick={mode.toggleMode}>
Current: {mode.mode} {/* "light" | "dark" */}
</button>
);
}

Open a side dialog for selecting entities from a collection. This is the same hook used internally when a relation property is rendered:

import { useEntitySelectionDialog } from "@rebasepro/core";
function SelectProduct() {
const selectionDialog = useEntitySelectionDialog({
path: "products",
collection: productsCollection,
onSingleEntitySelected: (entity) => {
console.log("Selected:", entity);
}
});
return <button onClick={selectionDialog.open}>Select Product</button>;
}

Access navigation state and resolved collections:

import { useNavigationController } from "@rebasepro/core";
function MyComponent() {
const navigation = useNavigationController();
navigation.collections // All registered collections
navigation.views // Custom views
navigation.adminViews // Admin-mode views
navigation.getCollection(path) // Get collection for a path
}

Manage complex relation selections with built-in search, debouncing, and pagination.

import { useRelationSelector } from "@rebasepro/core";
import { categoriesCollection } from "../config/collections";
function CategorySelector({ onSelect }) {
const { items, isLoading, search, loadMore, hasMore } = useRelationSelector({
path: "categories",
collection: categoriesCollection,
pageSize: 10
});
return (
<div>
<input type="text" onChange={(e) => search(e.target.value)} placeholder="Search..." />
<ul>
{items.map(item => (
<li key={item.id} onClick={() => onSelect(item.relation)}>
{item.label}
</li>
))}
</ul>
{hasMore && <button onClick={loadMore} disabled={isLoading}>Load More</button>}
</div>
);
}
OptionTypeDescription
pathstringAbsolute collection path.
collectionEntityCollectionTarget collection definition.
fixedFilterFilterValuesOptional. Static filters to restrict search results.
pageSizenumberOptional. Number of items per page. (Default: 10).
getLabelFromEntity(entity) => stringOptional. Customize the display label text.
getDescriptionFromEntity(entity) => stringOptional. Customize the description text.

Manage user account selection with server-side search and pagination, automatically falling back to client-side filtering if the backend delegate doesn’t support server-side search.

import { useUserSelector } from "@rebasepro/core";
function AssigneeSelector({ onSelect }) {
const { items, isLoading, search, loadMore, hasMore } = useUserSelector({
pageSize: 10
});
return (
<div>
<input type="text" onChange={(e) => search(e.target.value)} placeholder="Search users..." />
<ul>
{items.map(item => (
<li key={item.uid} onClick={() => onSelect(item.user)}>
{item.label} ({item.description})
</li>
))}
</ul>
{hasMore && <button onClick={loadMore} disabled={isLoading}>Load More</button>}
</div>
);
}
OptionTypeDescription
pageSizenumberOptional. Number of users to return per page. (Default: 10).
PropertyTypeDescription
itemsUserSelectorItem[]List of items wrapping uid, label, description, and raw user.
isLoadingbooleanTrue if fetching is active.
errorErrorContains error if fetch fails.
search(str) => voidUpdates search string with a debounced delay of 300ms.
loadMore() => voidLoads next page of users.
hasMorebooleanTrue if more users exist on the server.
getUser(uid) => UserHelper to fetch a single user object.

Retrieve the backing client SDK instance (RebaseClient) from the React context. This is useful for invoking raw SDK operations (like calling custom endpoints or manual uploads) within your components.

import { useRebaseClient } from "@rebasepro/core";
function CustomAction() {
const client = useRebaseClient();
const handleAction = async () => {
const result = await client.call("send-invoice", { invoiceId: "123" });
console.log(result);
};
return <button onClick={handleAction}>Process Invoice</button>;
}

Prevent navigation or page unload when form data has unsaved changes. It automatically intercepts internal React Router navigation via useBlocker as well as browser-level reloads via beforeunload.

import { useUnsavedChangesDialog } from "@rebasepro/core";
import { useState } from "react";
function EditForm() {
const [isDirty, setIsDirty] = useState(false);
const { dialogProps, triggerDialog } = useUnsavedChangesDialog(
isDirty,
() => console.log("Navigation allowed (discarded or saved changes)")
);
// dialogProps contains { open, handleOk, handleCancel, body }
}
ParameterTypeDescription
whenbooleanFlag to activate page/router navigation blocking.
onOk() => voidCallback triggered when the user confirms discarding changes.
PropertyTypeDescription
dialogPropsUnsavedChangesDialogPropsModal props to pass directly to an UnsavedChangesDialog UI component.
triggerDialog() => voidTriggers manual dialog display programmatically.

Switch roles at runtime to preview permissions and test Row-Level Security (RLS) policies locally without signing out.

import { useEffectiveRoleController } from "@rebasepro/core";
function RoleSwitcher() {
const { effectiveRole, setEffectiveRole } = useEffectiveRoleController();
return (
<select value={effectiveRole || ""} onChange={(e) => setEffectiveRole(e.target.value || null)}>
<option value="">Default (No Simulation)</option>
<option value="admin">Admin</option>
<option value="editor">Editor</option>
<option value="user">Standard User</option>
</select>
);
}

Switch the admin layout view modes within the admin panel.

import { useAdminModeController } from "@rebasepro/core";
function ModeToggle() {
const { mode, setMode } = useAdminModeController(); // mode is "content" | "studio" | "settings"
return <button onClick={() => setMode("studio")}>Switch to Studio View</button>;
}

Open dialog screens imperatively from anywhere in the component tree.

import { useDialogsController } from "@rebasepro/core";
import { MyCustomDialog } from "./MyCustomDialog";
function OpenModalButton() {
const dialogs = useDialogsController();
return (
<button onClick={() => dialogs.open({
key: "my-custom-modal",
Component: MyCustomDialog,
props: { title: "Custom Title" }
})}>
Open Custom Dialog
</button>
);
}

Capture CMS UI actions and user events globally.

import { useAnalyticsController } from "@rebasepro/core";
import { useEffect } from "react";
function AnalyticsLogger() {
const analytics = useAnalyticsController();
useEffect(() => {
analytics.onAnalyticsEvent = (event, data) => {
console.log(`CMS Event: ${event}`, data);
};
}, [analytics]);
}