React Hooks
Ramify JS exposes a single powerful hook useLiveQuery that enables any functional component to
reactively update when database content changes.
useLiveQuery<T>(callback, dependencies)
Executes the callback immediately and re-executes it whenever the dependent collections change.
Example:
import { useLiveQuery } from '@ramifyjs/react-hooks';
function MyComponent() {
const data = useLiveQuery(
() => {
// Your query logic here
return db.users.where('status').equals('active').toArray();
},
{
// Dependencies to watch for database changes
collections: [db.users],
// Other React dependencies (like props or state)
others: [],
}
);
return <div>{data?.length}</div>;
}
Parameters:
-
callback:() => T- A synchronous function that queries the database
- Runs on mount and whenever dependencies change
- Should return the query result
- Performance Note: The callback runs on every render and every database change. Keep it
fast. For expensive transformations, use
useMemoon the query result rather than in the callback.
-
dependencies:{ collections: readonly Subscribable[]; others: readonly unknown[] }collections:readonly Subscribable[]- Array of collections to observe
- When these collections emit a change (add/update/delete), the hook re-runs the callback
- Requirement: Must include all collections queried in the callback. If a collection is omitted, the component won't update when that collection changes.
others:readonly unknown[]- Array of standard React dependencies (like
useEffectdeps) - If these change, the hook also re-runs
- Include props, state, or other values used in the callback
- Array of standard React dependencies (like
Where Subscribable is defined as:
type Subscribable = {
subscribe: (cb: () => void) => () => void;
};
Returns: T | null
- Returns the result of the callback
- Returns
nullduring initial mount if the callback hasn't executed yet - Typically returns synchronously, so
nullis rare in practice
Usage Patterns
Reactive Query
Query all documents matching a criteria and reactively update when the collection changes.
function ActiveUsers() {
const activeUsers = useLiveQuery(() => db.users.where({ status: 'active' }).toArray(), {
collections: [db.users],
others: [],
});
return (
<div>
<h2>Active Users: {activeUsers?.length ?? 0}</h2>
{activeUsers?.map((user) => (
<div key={user.id}>{user.name}</div>
))}
</div>
);
}
Multiple Collections
Query across multiple collections and subscribe to all of them.
function UserMessages({ userId }: { userId: string }) {
const data = useLiveQuery(
() => {
const user = db.users.get(userId);
const messages = db.messages.where('senderId').equals(userId).toArray();
return { user, messages };
},
{
collections: [db.users, db.messages], // Subscribe to both collections
others: [userId],
}
);
return (
<div>
<h1>{data?.user?.name}</h1>
<h2>Messages: {data?.messages?.length ?? 0}</h2>
{data?.messages?.map((message) => (
<div key={message.id}>{message.content}</div>
))}
</div>
);
}