Live queries
Subscribe to a select and get its rows again every time they change.
A live query is a select that stays open. It sends the rows once, then sends them again each
time a write changes the result, whoever made the write.
In React
"use client";
import { useQuery } from "@shipmantis/sdk/react";
import { mantis } from "@/lib/mantis";
export function Todos() {
const { rows, error, loading } = useQuery(mantis, "todos", {
where: { done: false },
orderBy: [{ column: "createdAt", direction: "desc" }],
});
if (loading) return <p>Loading…</p>;
if (error) return <p>{error.message}</p>;
return (
<ul>
{rows!.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}useQuery(client, table, options) takes the same options as select and
returns:
| Field | What it holds |
|---|---|
rows | The latest rows, typed from the schema. undefined until the first answer. |
error | A MantisError if the query was refused. |
loading | true until the first rows or the first error. |
Change the options and the hook stops the old query and starts the new one. It stops when the component unmounts.
A browser holds the publishable key, not the secret one. Live queries made with it see only
what your access rules allow, so set the rules and a userToken
first.
Without React
const stop = mantis.from("todos").live(
{ where: { done: false } },
{
rows: (rows) => render(rows),
error: (error) => console.error(error.status, error.reasons),
},
);
// later
stop();live(options, handlers) calls rows with the whole result each time, not the change, so you
can render it as it is. It returns a function that stops the query. After an error the query
is stopped.
How it connects
The client opens one WebSocket to /v1/live on the first live query and shares it between all of
them. It closes the socket when the last one stops. With a userToken, a query refused because
the user's token expired asks for a new token and joins again.