From 133ab2bf5c7575dbc18431b3be87c6827ffbf0b8 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 10:54:56 +0000 Subject: [PATCH 1/2] test: add tests for multiple useLiveQuery instances with where + orderBy (issue #1208) Adds comprehensive tests for the scenario described in the issue where multiple components using the same useLiveQuery with where + orderBy clauses should show consistent data. These tests cover: - Multiple useLiveQuery hooks with identical queries - Items moving in/out of filter range when updated - Rapid consecutive updates across all query instances - Rendered components with the same query showing identical data - Interleaved updates without data loss All tests currently pass, suggesting the issue may be environment-specific or require additional conditions to reproduce. Co-Authored-By: Claude Opus 4.6 --- .../useLiveQuery-multiple-components.test.tsx | 669 ++++++++++++++++++ 1 file changed, 669 insertions(+) create mode 100644 packages/solid-db/tests/useLiveQuery-multiple-components.test.tsx diff --git a/packages/solid-db/tests/useLiveQuery-multiple-components.test.tsx b/packages/solid-db/tests/useLiveQuery-multiple-components.test.tsx new file mode 100644 index 000000000..ff2bd3c7e --- /dev/null +++ b/packages/solid-db/tests/useLiveQuery-multiple-components.test.tsx @@ -0,0 +1,669 @@ +import { describe, expect, it } from 'vitest' +import { render, renderHook, waitFor } from '@solidjs/testing-library' +import { + and, + createCollection, + gte, + lte, +} from '@tanstack/db' +import { For, createEffect } from 'solid-js' +import { useLiveQuery } from '../src/useLiveQuery' +import { mockSyncCollectionOptions } from '../../db/tests/utils' + +type Item = { + id: string + index: number + name: string +} + +const createInitialItems = (): Array => [ + { id: `a`, index: 1, name: `Item A` }, + { id: `b`, index: 2, name: `Item B` }, + { id: `c`, index: 3, name: `Item C` }, + { id: `d`, index: 4, name: `Item D` }, + { id: `e`, index: 5, name: `Item E` }, +] + +describe(`Multiple useLiveQuery instances with where + orderBy`, () => { + it(`should maintain consistent data when updating items that move in/out of filter range with limit`, async () => { + // This test reproduces the scenario from the issue report: + // - Multiple components using the same query with where + orderBy + limit + // - Items are updated in ways that cause them to move in/out of the filter range + // - Each update should result in all query instances showing identical data + + const collection = createCollection( + mockSyncCollectionOptions({ + id: `filter-boundary-test`, + getKey: (item: Item) => item.id, + initialData: createInitialItems(), + }), + ) + + // Track state snapshots from multiple hooks + const stateSnapshots: Array> = [] + + // Create 4 query hooks with where + orderBy + limit (as in the issue) + const queries = [1, 2, 3, 4].map(() => + renderHook(() => { + const query = useLiveQuery((q) => + q + .from({ items: collection }) + .where(({ items }) => and(gte(items.index, 1), lte(items.index, 4))) + .select(({ items }) => ({ + id: items.id, + index: items.index, + name: items.name, + })) + .orderBy(({ items }) => items.index, `asc`) + .limit(10), + ) + + // Track each query's effect updates + createEffect(() => { + const data = query() + stateSnapshots.push([...data]) + }) + + return query + }), + ) + + // Wait for initial sync + await waitFor(() => { + for (const query of queries) { + expect(query.result.state.size).toBe(4) + } + }) + + // Clear snapshots to start fresh + stateSnapshots.length = 0 + + // Simulate the "decrement all" operation from the issue + // This causes item 'a' (index 1) to move out of range (index 0) + // and item 'e' (index 5) to move into range (index 4) + collection.utils.begin() + for (const id of [`a`, `b`, `c`, `d`, `e`]) { + const current = collection.get(id) + if (current) { + collection.utils.write({ + type: `update`, + value: { ...current, index: current.index - 1 }, + }) + } + } + collection.utils.commit() + + // Wait for all queries to update + await new Promise((resolve) => setTimeout(resolve, 100)) + + // All queries should now show items b, c, d, e (indices 1, 2, 3, 4) + for (const query of queries) { + const ids = query.result().map((item) => item.id).sort() + expect(ids).toEqual([`b`, `c`, `d`, `e`]) + } + + // Verify all 4 queries show identical data (the core assertion for this bug) + const allResults = queries.map((q) => + q.result().map((item) => `${item.id}:${item.index}`).sort().join(','), + ) + const uniqueResults = [...new Set(allResults)] + expect(uniqueResults.length).toBe(1) // All queries should show the same result + + // Now simulate "change name" which doesn't affect filter but does update items + stateSnapshots.length = 0 + collection.utils.begin() + for (const id of [`b`, `c`, `d`, `e`]) { + const current = collection.get(id) + if (current) { + collection.utils.write({ + type: `update`, + value: { ...current, name: current.name + `+` }, + }) + } + } + collection.utils.commit() + + // Wait for all queries to update + await new Promise((resolve) => setTimeout(resolve, 100)) + + // Verify all queries show the same updated names + const allNames = queries.map((q) => + q.result().map((item) => item.name).sort().join(','), + ) + const uniqueNames = [...new Set(allNames)] + expect(uniqueNames.length).toBe(1) + + // Check that names were actually updated + for (const query of queries) { + const names = query.result().map((item) => item.name) + for (const name of names) { + expect(name).toContain(`+`) + } + } + }) + + it(`should maintain consistent data across multiple query instances when items are updated`, async () => { + const collection = createCollection( + mockSyncCollectionOptions({ + id: `multiple-queries-test`, + getKey: (item: Item) => item.id, + initialData: createInitialItems(), + }), + ) + + // Create 4 independent useLiveQuery hooks with the same query + // (simulating 4 List components as in the bug report) + const query1 = renderHook(() => { + return useLiveQuery((q) => + q + .from({ items: collection }) + .where(({ items }) => and(gte(items.index, 1), lte(items.index, 4))) + .select(({ items }) => ({ + id: items.id, + index: items.index, + name: items.name, + })) + .orderBy(({ items }) => items.index, `asc`), + ) + }) + + const query2 = renderHook(() => { + return useLiveQuery((q) => + q + .from({ items: collection }) + .where(({ items }) => and(gte(items.index, 1), lte(items.index, 4))) + .select(({ items }) => ({ + id: items.id, + index: items.index, + name: items.name, + })) + .orderBy(({ items }) => items.index, `asc`), + ) + }) + + const query3 = renderHook(() => { + return useLiveQuery((q) => + q + .from({ items: collection }) + .where(({ items }) => and(gte(items.index, 1), lte(items.index, 4))) + .select(({ items }) => ({ + id: items.id, + index: items.index, + name: items.name, + })) + .orderBy(({ items }) => items.index, `asc`), + ) + }) + + const query4 = renderHook(() => { + return useLiveQuery((q) => + q + .from({ items: collection }) + .where(({ items }) => and(gte(items.index, 1), lte(items.index, 4))) + .select(({ items }) => ({ + id: items.id, + index: items.index, + name: items.name, + })) + .orderBy(({ items }) => items.index, `asc`), + ) + }) + + // Wait for all queries to sync + await waitFor(() => { + expect(query1.result.state.size).toBe(4) + expect(query2.result.state.size).toBe(4) + expect(query3.result.state.size).toBe(4) + expect(query4.result.state.size).toBe(4) + }) + + // Verify all queries show the same initial data + const getItemIds = (query: typeof query1) => + query.result().map((item) => item.id).sort() + + expect(getItemIds(query1)).toEqual([`a`, `b`, `c`, `d`]) + expect(getItemIds(query2)).toEqual([`a`, `b`, `c`, `d`]) + expect(getItemIds(query3)).toEqual([`a`, `b`, `c`, `d`]) + expect(getItemIds(query4)).toEqual([`a`, `b`, `c`, `d`]) + + // Decrement all indices (simulating the "decrement all" button) + collection.utils.begin() + collection.utils.write({ + type: `update`, + value: { id: `a`, index: 0, name: `Item A` }, + }) + collection.utils.write({ + type: `update`, + value: { id: `b`, index: 1, name: `Item B` }, + }) + collection.utils.write({ + type: `update`, + value: { id: `c`, index: 2, name: `Item C` }, + }) + collection.utils.write({ + type: `update`, + value: { id: `d`, index: 3, name: `Item D` }, + }) + collection.utils.write({ + type: `update`, + value: { id: `e`, index: 4, name: `Item E` }, + }) + collection.utils.commit() + + // Wait for updates to propagate + await waitFor(() => { + // After decrement, indices are 0,1,2,3,4 + // Where clause filters to indices 1-4, so items b,c,d,e should be visible + expect(query1.result.state.size).toBe(4) + }) + + // All 4 queries should show the same updated data + // Items with index 1-4 are: b(1), c(2), d(3), e(4) + await waitFor(() => { + expect(getItemIds(query1)).toEqual([`b`, `c`, `d`, `e`]) + expect(getItemIds(query2)).toEqual([`b`, `c`, `d`, `e`]) + expect(getItemIds(query3)).toEqual([`b`, `c`, `d`, `e`]) + expect(getItemIds(query4)).toEqual([`b`, `c`, `d`, `e`]) + }) + + // Now update names (simulating the "change name" button) + collection.utils.begin() + collection.utils.write({ + type: `update`, + value: { id: `b`, index: 1, name: `Item B+` }, + }) + collection.utils.write({ + type: `update`, + value: { id: `c`, index: 2, name: `Item C+` }, + }) + collection.utils.write({ + type: `update`, + value: { id: `d`, index: 3, name: `Item D+` }, + }) + collection.utils.write({ + type: `update`, + value: { id: `e`, index: 4, name: `Item E+` }, + }) + collection.utils.commit() + + // Wait for name updates and verify all queries are consistent + await waitFor(() => { + const names1 = query1.result().map((item) => item.name).sort() + const names2 = query2.result().map((item) => item.name).sort() + const names3 = query3.result().map((item) => item.name).sort() + const names4 = query4.result().map((item) => item.name).sort() + + expect(names1).toEqual([`Item B+`, `Item C+`, `Item D+`, `Item E+`]) + expect(names2).toEqual([`Item B+`, `Item C+`, `Item D+`, `Item E+`]) + expect(names3).toEqual([`Item B+`, `Item C+`, `Item D+`, `Item E+`]) + expect(names4).toEqual([`Item B+`, `Item C+`, `Item D+`, `Item E+`]) + }) + + // Verify ordering is correct (by index ascending) + const getOrderedIndices = (query: typeof query1) => + query.result().map((item) => item.index) + + expect(getOrderedIndices(query1)).toEqual([1, 2, 3, 4]) + expect(getOrderedIndices(query2)).toEqual([1, 2, 3, 4]) + expect(getOrderedIndices(query3)).toEqual([1, 2, 3, 4]) + expect(getOrderedIndices(query4)).toEqual([1, 2, 3, 4]) + }) + + it(`should correctly update all query instances when items move in and out of filter range`, async () => { + const collection = createCollection( + mockSyncCollectionOptions({ + id: `filter-range-test`, + getKey: (item: Item) => item.id, + initialData: createInitialItems(), + }), + ) + + // Create multiple useLiveQuery hooks + const queries = [1, 2, 3, 4].map(() => + renderHook(() => { + return useLiveQuery((q) => + q + .from({ items: collection }) + .where(({ items }) => and(gte(items.index, 2), lte(items.index, 4))) + .select(({ items }) => ({ + id: items.id, + index: items.index, + name: items.name, + })) + .orderBy(({ items }) => items.index, `asc`), + ) + }), + ) + + // Wait for initial sync - items b(2), c(3), d(4) should be visible + await waitFor(() => { + for (const query of queries) { + expect(query.result.state.size).toBe(3) + } + }) + + const getAllIds = () => + queries.map((q) => + q.result().map((item) => item.id).sort(), + ) + + // Verify initial state + const initialIds = getAllIds() + for (const ids of initialIds) { + expect(ids).toEqual([`b`, `c`, `d`]) + } + + // Move item 'a' into range (index 1 -> 3) + collection.utils.begin() + collection.utils.write({ + type: `update`, + value: { id: `a`, index: 3, name: `Item A` }, + }) + // Move item 'b' out of range (index 2 -> 1) + collection.utils.write({ + type: `update`, + value: { id: `b`, index: 1, name: `Item B` }, + }) + collection.utils.commit() + + // After update: a(3), c(3), d(4) should be visible (b is now at index 1, out of range) + // Wait for updates + await waitFor(() => { + for (const query of queries) { + expect(query.result.state.size).toBe(3) + } + }) + + // Verify all queries show consistent data + const updatedIds = getAllIds() + for (const ids of updatedIds) { + expect(ids).toEqual([`a`, `c`, `d`]) + } + }) + + it(`should handle rapid consecutive updates correctly across all query instances`, async () => { + const collection = createCollection( + mockSyncCollectionOptions({ + id: `rapid-updates-test`, + getKey: (item: Item) => item.id, + initialData: createInitialItems(), + }), + ) + + // Create multiple useLiveQuery hooks + const queries = [1, 2, 3, 4].map(() => + renderHook(() => { + return useLiveQuery((q) => + q + .from({ items: collection }) + .where(({ items }) => and(gte(items.index, 1), lte(items.index, 4))) + .select(({ items }) => ({ + id: items.id, + index: items.index, + name: items.name, + })) + .orderBy(({ items }) => items.index, `asc`), + ) + }), + ) + + // Wait for initial sync + await waitFor(() => { + for (const query of queries) { + expect(query.result.state.size).toBe(4) + } + }) + + // Perform rapid consecutive updates (simulating multiple button clicks) + for (let i = 0; i < 3; i++) { + collection.utils.begin() + // Decrement all indices + for (const id of [`a`, `b`, `c`, `d`, `e`]) { + const current = collection.get(id) + if (current) { + collection.utils.write({ + type: `update`, + value: { ...current, index: current.index - 1 }, + }) + } + } + collection.utils.commit() + } + + // Wait for all updates to settle + await new Promise((resolve) => setTimeout(resolve, 100)) + + // After 3 decrements: a(-2), b(-1), c(0), d(1), e(2) + // Only d(1) and e(2) should be in range [1, 4] + await waitFor(() => { + for (const query of queries) { + const ids = query.result().map((item) => item.id).sort() + expect(ids).toEqual([`d`, `e`]) + } + }) + + // Verify all queries have consistent ordering + for (const query of queries) { + const indices = query.result().map((item) => item.index) + expect(indices).toEqual([1, 2]) + } + }) + + it(`should render identical data in multiple List components using the same query with limit`, async () => { + const collection = createCollection( + mockSyncCollectionOptions({ + id: `render-test`, + getKey: (item: Item) => item.id, + initialData: createInitialItems(), + }), + ) + + // Track rendered data from each List component + const renderedData: Array> = [[], [], [], []] + + function ListComponent(props: { index: number }) { + const query = useLiveQuery((q) => + q + .from({ items: collection }) + .where(({ items }) => and(gte(items.index, 1), lte(items.index, 4))) + .select(({ items }) => ({ + id: items.id, + index: items.index, + name: items.name, + })) + .orderBy(({ items }) => items.index, `asc`) + .limit(10), // Adding limit to match the user's reproduction case + ) + + // Track what this component renders + createEffect(() => { + const data = query() + renderedData[props.index] = data.map((item) => `${item.id}:${item.index}:${item.name}`) + }) + + return ( +
    + + {(item) => ( +
  • + {item.name} ({item.index}) +
  • + )} +
    +
+ ) + } + + const { findByTestId } = render(() => ( +
+ + + + +
+ )) + + // Wait for initial render + await waitFor(async () => { + const list0 = await findByTestId(`list-0`) + expect(list0.children.length).toBe(4) + }) + + // Verify all lists show the same data + await waitFor(() => { + for (let i = 1; i < 4; i++) { + expect(renderedData[i]).toEqual(renderedData[0]) + } + }) + + // Perform an update (decrement all) + collection.utils.begin() + for (const id of [`a`, `b`, `c`, `d`, `e`]) { + const current = collection.get(id) + if (current) { + collection.utils.write({ + type: `update`, + value: { ...current, index: current.index - 1 }, + }) + } + } + collection.utils.commit() + + // Wait for updates to propagate + await new Promise((resolve) => setTimeout(resolve, 100)) + + // Verify all lists still show the same data after update + await waitFor(() => { + // All lists should render b,c,d,e (indices 1,2,3,4 after decrement) + for (let i = 0; i < 4; i++) { + expect(renderedData[i].length).toBe(4) + } + }) + + // Verify consistency: all lists should render identical data + for (let i = 1; i < 4; i++) { + expect(renderedData[i]).toEqual(renderedData[0]) + } + + // Perform another update (change names) + collection.utils.begin() + for (const id of [`a`, `b`, `c`, `d`, `e`]) { + const current = collection.get(id) + if (current) { + collection.utils.write({ + type: `update`, + value: { ...current, name: current.name + `+` }, + }) + } + } + collection.utils.commit() + + // Wait for name updates + await new Promise((resolve) => setTimeout(resolve, 100)) + + // Verify all lists show the same updated names + await waitFor(() => { + for (let i = 0; i < 4; i++) { + expect(renderedData[i].some((s) => s.includes(`+`))).toBe(true) + } + }) + + // Verify consistency again + for (let i = 1; i < 4; i++) { + expect(renderedData[i]).toEqual(renderedData[0]) + } + }) + + it(`should handle interleaved updates correctly without data loss`, async () => { + // This test checks for potential race conditions where updates might + // be processed differently by different useLiveQuery instances + + const collection = createCollection( + mockSyncCollectionOptions({ + id: `interleaved-updates-test`, + getKey: (item: Item) => item.id, + initialData: createInitialItems(), + }), + ) + + // Create multiple useLiveQuery hooks + const queries = [1, 2, 3, 4].map(() => + renderHook(() => { + return useLiveQuery((q) => + q + .from({ items: collection }) + .where(({ items }) => and(gte(items.index, 1), lte(items.index, 4))) + .select(({ items }) => ({ + id: items.id, + index: items.index, + name: items.name, + })) + .orderBy(({ items }) => items.index, `asc`) + .limit(10), + ) + }), + ) + + // Wait for initial sync + await waitFor(() => { + for (const query of queries) { + expect(query.result.state.size).toBe(4) + } + }) + + // Perform multiple rapid updates + for (let round = 0; round < 5; round++) { + // Update all items + collection.utils.begin() + for (const id of [`a`, `b`, `c`, `d`, `e`]) { + const current = collection.get(id) + if (current) { + collection.utils.write({ + type: `update`, + value: { ...current, name: current.name + round }, + }) + } + } + collection.utils.commit() + + // Small delay to allow some async processing + await new Promise((resolve) => setTimeout(resolve, 10)) + + // Decrement indices + collection.utils.begin() + for (const id of [`a`, `b`, `c`, `d`, `e`]) { + const current = collection.get(id) + if (current) { + collection.utils.write({ + type: `update`, + value: { ...current, index: current.index - 1 }, + }) + } + } + collection.utils.commit() + + // Small delay + await new Promise((resolve) => setTimeout(resolve, 10)) + } + + // Wait for all updates to settle + await new Promise((resolve) => setTimeout(resolve, 200)) + + // All queries should show identical data + const allResultsData = queries.map((q) => + q.result().map((item) => JSON.stringify(item)).sort().join('|'), + ) + const uniqueResults = [...new Set(allResultsData)] + + // The critical assertion: all queries must show identical data + expect(uniqueResults.length).toBe(1) + + // Verify the results are consistent arrays (all items typed correctly) + // Note: after 5 rounds of decrementing indices, all items may be out of range + // which is expected behavior + for (const query of queries) { + const data = query.result() + expect(Array.isArray(data)).toBe(true) + } + }) +}) From 941d902394db7d616e7e1f08b1728e63f8846e09 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 10:56:10 +0000 Subject: [PATCH 2/2] ci: apply automated fixes --- .../useLiveQuery-multiple-components.test.tsx | 96 +++++++++++++------ 1 file changed, 66 insertions(+), 30 deletions(-) diff --git a/packages/solid-db/tests/useLiveQuery-multiple-components.test.tsx b/packages/solid-db/tests/useLiveQuery-multiple-components.test.tsx index ff2bd3c7e..563bf321d 100644 --- a/packages/solid-db/tests/useLiveQuery-multiple-components.test.tsx +++ b/packages/solid-db/tests/useLiveQuery-multiple-components.test.tsx @@ -1,11 +1,6 @@ import { describe, expect, it } from 'vitest' import { render, renderHook, waitFor } from '@solidjs/testing-library' -import { - and, - createCollection, - gte, - lte, -} from '@tanstack/db' +import { and, createCollection, gte, lte } from '@tanstack/db' import { For, createEffect } from 'solid-js' import { useLiveQuery } from '../src/useLiveQuery' import { mockSyncCollectionOptions } from '../../db/tests/utils' @@ -40,7 +35,9 @@ describe(`Multiple useLiveQuery instances with where + orderBy`, () => { ) // Track state snapshots from multiple hooks - const stateSnapshots: Array> = [] + const stateSnapshots: Array< + Array<{ id: string; index: number; name: string }> + > = [] // Create 4 query hooks with where + orderBy + limit (as in the issue) const queries = [1, 2, 3, 4].map(() => @@ -98,13 +95,20 @@ describe(`Multiple useLiveQuery instances with where + orderBy`, () => { // All queries should now show items b, c, d, e (indices 1, 2, 3, 4) for (const query of queries) { - const ids = query.result().map((item) => item.id).sort() + const ids = query + .result() + .map((item) => item.id) + .sort() expect(ids).toEqual([`b`, `c`, `d`, `e`]) } // Verify all 4 queries show identical data (the core assertion for this bug) const allResults = queries.map((q) => - q.result().map((item) => `${item.id}:${item.index}`).sort().join(','), + q + .result() + .map((item) => `${item.id}:${item.index}`) + .sort() + .join(','), ) const uniqueResults = [...new Set(allResults)] expect(uniqueResults.length).toBe(1) // All queries should show the same result @@ -128,7 +132,11 @@ describe(`Multiple useLiveQuery instances with where + orderBy`, () => { // Verify all queries show the same updated names const allNames = queries.map((q) => - q.result().map((item) => item.name).sort().join(','), + q + .result() + .map((item) => item.name) + .sort() + .join(','), ) const uniqueNames = [...new Set(allNames)] expect(uniqueNames.length).toBe(1) @@ -219,7 +227,10 @@ describe(`Multiple useLiveQuery instances with where + orderBy`, () => { // Verify all queries show the same initial data const getItemIds = (query: typeof query1) => - query.result().map((item) => item.id).sort() + query + .result() + .map((item) => item.id) + .sort() expect(getItemIds(query1)).toEqual([`a`, `b`, `c`, `d`]) expect(getItemIds(query2)).toEqual([`a`, `b`, `c`, `d`]) @@ -288,10 +299,22 @@ describe(`Multiple useLiveQuery instances with where + orderBy`, () => { // Wait for name updates and verify all queries are consistent await waitFor(() => { - const names1 = query1.result().map((item) => item.name).sort() - const names2 = query2.result().map((item) => item.name).sort() - const names3 = query3.result().map((item) => item.name).sort() - const names4 = query4.result().map((item) => item.name).sort() + const names1 = query1 + .result() + .map((item) => item.name) + .sort() + const names2 = query2 + .result() + .map((item) => item.name) + .sort() + const names3 = query3 + .result() + .map((item) => item.name) + .sort() + const names4 = query4 + .result() + .map((item) => item.name) + .sort() expect(names1).toEqual([`Item B+`, `Item C+`, `Item D+`, `Item E+`]) expect(names2).toEqual([`Item B+`, `Item C+`, `Item D+`, `Item E+`]) @@ -344,7 +367,10 @@ describe(`Multiple useLiveQuery instances with where + orderBy`, () => { const getAllIds = () => queries.map((q) => - q.result().map((item) => item.id).sort(), + q + .result() + .map((item) => item.id) + .sort(), ) // Verify initial state @@ -437,7 +463,10 @@ describe(`Multiple useLiveQuery instances with where + orderBy`, () => { // Only d(1) and e(2) should be in range [1, 4] await waitFor(() => { for (const query of queries) { - const ids = query.result().map((item) => item.id).sort() + const ids = query + .result() + .map((item) => item.id) + .sort() expect(ids).toEqual([`d`, `e`]) } }) @@ -462,23 +491,26 @@ describe(`Multiple useLiveQuery instances with where + orderBy`, () => { const renderedData: Array> = [[], [], [], []] function ListComponent(props: { index: number }) { - const query = useLiveQuery((q) => - q - .from({ items: collection }) - .where(({ items }) => and(gte(items.index, 1), lte(items.index, 4))) - .select(({ items }) => ({ - id: items.id, - index: items.index, - name: items.name, - })) - .orderBy(({ items }) => items.index, `asc`) - .limit(10), // Adding limit to match the user's reproduction case + const query = useLiveQuery( + (q) => + q + .from({ items: collection }) + .where(({ items }) => and(gte(items.index, 1), lte(items.index, 4))) + .select(({ items }) => ({ + id: items.id, + index: items.index, + name: items.name, + })) + .orderBy(({ items }) => items.index, `asc`) + .limit(10), // Adding limit to match the user's reproduction case ) // Track what this component renders createEffect(() => { const data = query() - renderedData[props.index] = data.map((item) => `${item.id}:${item.index}:${item.name}`) + renderedData[props.index] = data.map( + (item) => `${item.id}:${item.index}:${item.name}`, + ) }) return ( @@ -651,7 +683,11 @@ describe(`Multiple useLiveQuery instances with where + orderBy`, () => { // All queries should show identical data const allResultsData = queries.map((q) => - q.result().map((item) => JSON.stringify(item)).sort().join('|'), + q + .result() + .map((item) => JSON.stringify(item)) + .sort() + .join('|'), ) const uniqueResults = [...new Set(allResultsData)]