-
Notifications
You must be signed in to change notification settings - Fork 140
Open
Description
I’ve been trying to get TanStack DB working in a Next.js app, but I keep running into issues.
The main problem is a Missing getServerSnapshot runtime error.
Even though the component is explicitly marked as a client component, Next.js still throws an error indicating that the component attempted to render on the server.
So far, the only workaround I’ve found is fairly heavy:
- Move all code that uses useLiveQuery into a separate client-only component
- Dynamically import that component using next/dynamic
- Extract collection creation into a factory function (e.g. createToDoCollection()) and initialize it inside the client component
- Wrap the server action used by queryFn in a Promise, and defer it with queueMicrotask() to ensure it runs outside of React’s render phase
This setup works, but It's clearly not logical.
Is TanStack DB currently not fully compatible with Next.js (App Router) yet, or is there a recommended pattern for using it without these workarounds?
Package versions:
"@tanstack/query-db-collection": "^1.0.7",
"@tanstack/react-db": "^0.1.56",
"@tanstack/react-query": "^5.90.12",
"next": "^16.0.10",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"zod": "^3.25.76",
"typescript": "^5.9.3"Full code: (Throws errors)
"use client";
import { todoCollection } from "@/lib/todo-collection";
import { eq, useLiveQuery } from "@tanstack/react-db";
import { Button } from "@workspace/ui/components/shadcn/button";
export default function TodosPage() {
// Basic filtering and sorting
const { data: incompleteTodos } = useLiveQuery((q) =>
q
.from({ todo: todoCollection })
.where(({ todo }) => eq(todo.completed, false))
.orderBy(({ todo }) => todo.createdAt, "desc")
);
const addTodo = () => {
todoCollection.insert({
id: crypto.randomUUID(),
text: "New todo",
completed: false,
priority: 0,
createdAt: new Date(),
});
};
return (
<div className="flex flex-col items-center justify-center gap-4 py-20">
<div className="border rounded-xl p-10">
<h1 className="text-2xl font-bold">Todos</h1>
<Button onClick={addTodo}>Add Todo</Button>
<ul>
{incompleteTodos?.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
</div>
</div>
);
}I can provide a full "working" example with all these workaround fixed if needed; or share a screen recording.

Metadata
Metadata
Assignees
Labels
No labels