Skip to content

Nested includes are undefined on next render after collection.update #1635

Description

@KN3LL2K
  • 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:

  1. Setup nested include collection like above example
  2. Call collection.update where collection is the parent collection (documentCollection in example)
  3. Observe nested objects are now undefined
  4. Refresh the page
  5. 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
  </>
)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions