Nested includes are undefined on next render after collection.update
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 3.9k
- Forks
- 266
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 55
Description
- I've validated the bug against the latest version of DB packages
Packages:
"@tanstack/db": "^0.6.7",
"@tanstack/electric-db-collection": "^0.3.5",
"@tanstack/react-db": "^0.1.85",
Describe the bug
I have a useLiveQuery with nested collections. When I call update on the parent collection, the nested collections are undefined. Sometimes refreshing the page the nested items are still undefined. A hard refresh is required.
This is using electric-sync. I can see the successful write call and shape update with matching txid.
If you force a re-render, the nested objects appear. See Additional Context below.
// collection
// the other two collection funcs are almost identical
export const createDocumentCollection = (labId: number) =>
createCollection(
electricCollectionOptions<DocumentRow>({
id: `documents:${labId}`,
shapeOptions: {
url: electricSyncUrl,
params: {
table: 'documents',
where: 'lab_id = $1',
params: { '1': String(labId) },
columns: SYNC_COLUMNS,
},
fetchClient: (input, init) => fetch(input, { ...init, credentials: 'include' }),
columnMapper: snakeCamelMapper(),
parser: {
data: (data) => JSON.parse(data),
},
},
getKey: (row) => row.id,
onUpdate: async ({ transaction }) => {
const { original, changes } = transaction.mutations[0]
const response = await DocumentService.updateDocument(labId, original.id, changes)
return { txid: response.txid }
},
})
)
// query
const { data: documentQuery } = useLiveQuery(
(q) =>
q
.from({ document: documentCollection })
.where(({ document }) => eq(document.id, documentId))
.select(({ document }) => ({
...,
schema: toArray(
q
.from({ schema: schemaCollection })
.where(({ schema }) => eq(document.schemaId, schema.id))
.select(({ schema }) => ({
...,
fields: toArray(
q
.from({ field: fieldCollection })
.where(({ field }) => eq(field.schemaId, schema.id))
.select(({ field }) => field)
),
}))
),
})),
[documentCollection, schemaCollection, fieldCollection, documentId]
)
const document = documentQuery[0]
const schema = document.schema[0] // comes up undefined
const fields = schema?.[0].fields ?? []
const update = (name: string, v: string) => {
return documentCollection.update(documentId, (draft) => {
draft[name] = v
})
}
To Reproduce
Steps to reproduce the behavior:
- Setup nested include collection like above example
- Call collection.update where collection is the parent collection (documentCollection in example)
- Observe nested objects are now undefined
- Refresh the page
- Observe nested objects are now undefined
Expected behavior
I would expect the nested data to render after the update.
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop:
- OS: macOS
- Browser: chrome
- Version 148.0.7778.97
Additional context
If i add a simple useState counter to force a re-render, the nested collections appear
const [count, setCount] = useState(0)
return (
<>
<button onClick={() => setCount((c) => c + 1)}>{count}</button>
...rest of my component
</>
)
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 useLiveQuery nested query and the parent documentCollection.update call shown in the reproduction. Reproduce the issue with the document, schema, and field collections, then trace how the update propagates to nested results. Done means nested schema and field data render after collection.update and refresh without forcing an unrelated React re-render.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- databases, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100