Svelte: toArray sub-queries returning null values when inspected
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 3.9k
- Forks
- 266
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 55
Description
- [ x] I've validated the bug against the latest version of DB packages
Describe the bug
When using svelte-db, queries that involve a toArray sub query become unstable and produce null values (mainly on item insert, but has also caused issues with the entire dataset) while the query is inspected with the $inspect rune.
To Reproduce
In this basic reproduction, the code will throw an error as follows: TypeError: can't access property "length", $.get(...).comments is null. This is mainly when the new item button is pressed and an item is inserted, but also on the first page load. If you remove the $inspect on the query, the behaviour returns to the standard and the toArray is initialized correctly with each item.
<script lang="ts">
import { useLiveQuery, toArray, eq } from "@tanstack/svelte-db";
import { query_client } from "$lib/query.svelte";
import { GetComments } from "$lib/remote/comments.remote";
import { CreateTask, GetTasks } from "$lib/remote/tasks.remote";
import { createCollection } from "@tanstack/db";
import { queryCollectionOptions } from "@tanstack/query-db-collection";
const TaskCollection = createCollection(
queryCollectionOptions({
queryKey: ["tasks"],
queryFn: async () => {
const tasks = await GetTasks().run();
return tasks;
},
getKey: (task) => task.id,
queryClient: query_client,
onInsert: async ({ transaction }) => {
await Promise.all(
transaction.mutations.map((mut) => {
return CreateTask(mut.modified);
}),
);
query_client.invalidateQueries({ queryKey: ["tasks"] });
},
}),
);
const CommentsCollection = createCollection(
queryCollectionOptions({
queryKey: ["comments"],
queryFn: async () => {
const comments = await GetComments().run();
return comments;
},
queryClient: query_client,
getKey: (comment) => comment.id,
}),
);
const query = useLiveQuery((q) =>
q.from({ task: TaskCollection }).select(({ task }) => ({
id: task.id,
title: task.title,
comments: toArray(
q
.from({ comment: CommentsCollection })
.where(({ comment }) => eq(task.id, comment.task_id)),
),
})),
);
$inspect(query);
</script>
{#each query.data as task (task.id)}
<p>{task.title} ({task.comments.length} Comments)</p>
{/each}
<button
onclick={() =>
TaskCollection.insert({
id: crypto.randomUUID(),
title: `Task ${crypto.randomUUID()}`,
priority: 1,
})}>New Task</button
>
Expected behavior
The expected behaviour is that adding an inspect to view the output of a query should not affect the reactivity of the contents, and that the data output aligns with the expected type. In this case, toArray does not display as a nullable type.
Screenshots
Desktop (please complete the following information):
- OS: MacOS
- Browser: Chrome & Zen
- Version: (Chrome: 147.0.7727.102, Zen: 1.19.4b)
Additional context
N/A
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the provided Svelte reproduction, focusing on the useLiveQuery query that combines toArray with the $inspect rune and the insert handler. Verify the behavior on initial load and after inserting a task; done means inspected queries retain initialized comment arrays and no longer produce null values or the reported length error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100