( configOrQueryOrCollection: any, deps: Array<unknown> = [], )
| 314 | |
| 315 | // Implementation - use function overloads to infer the actual collection type |
| 316 | export function useLiveQuery( |
| 317 | configOrQueryOrCollection: any, |
| 318 | deps: Array<unknown> = [], |
| 319 | ) { |
| 320 | // Check if it's already a collection by checking for specific collection methods |
| 321 | const isCollection = |
| 322 | configOrQueryOrCollection && |
| 323 | typeof configOrQueryOrCollection === `object` && |
| 324 | typeof configOrQueryOrCollection.subscribeChanges === `function` && |
| 325 | typeof configOrQueryOrCollection.startSyncImmediate === `function` && |
| 326 | typeof configOrQueryOrCollection.id === `string` |
| 327 | |
| 328 | // Use refs to cache collection and track dependencies |
| 329 | const collectionRef = useRef<Collection<object, string | number, {}> | null>( |
| 330 | null, |
| 331 | ) |
| 332 | const depsRef = useRef<Array<unknown> | null>(null) |
| 333 | const configRef = useRef<unknown>(null) |
| 334 | |
| 335 | // Use refs to track version and memoized snapshot |
| 336 | const versionRef = useRef(0) |
| 337 | const snapshotRef = useRef<{ |
| 338 | collection: Collection<object, string | number, {}> | null |
| 339 | version: number |
| 340 | } | null>(null) |
| 341 | |
| 342 | // Check if we need to create/recreate the collection |
| 343 | const needsNewCollection = |
| 344 | !collectionRef.current || |
| 345 | (isCollection && configRef.current !== configOrQueryOrCollection) || |
| 346 | (!isCollection && |
| 347 | (depsRef.current === null || |
| 348 | depsRef.current.length !== deps.length || |
| 349 | depsRef.current.some((dep, i) => dep !== deps[i]))) |
| 350 | |
| 351 | if (needsNewCollection) { |
| 352 | if (isCollection) { |
| 353 | // Warn when passing a collection directly with on-demand sync mode |
| 354 | // In on-demand mode, data is only loaded when queries with predicates request it |
| 355 | // Passing the collection directly doesn't provide any predicates, so no data loads |
| 356 | const syncMode = ( |
| 357 | configOrQueryOrCollection as { config?: { syncMode?: string } } |
| 358 | ).config?.syncMode |
| 359 | if (syncMode === `on-demand`) { |
| 360 | console.warn( |
| 361 | `[useLiveQuery] Warning: Passing a collection with syncMode "on-demand" directly to useLiveQuery ` + |
| 362 | `will not load any data. In on-demand mode, data is only loaded when queries with predicates request it.\n\n` + |
| 363 | `Instead, use a query builder function:\n` + |
| 364 | ` const { data } = useLiveQuery((q) => q.from({ c: myCollection }).select(({ c }) => c))\n\n` + |
| 365 | `Or switch to syncMode "eager" if you want all data to sync automatically.`, |
| 366 | ) |
| 367 | } |
| 368 | // It's already a collection, ensure sync is started for React hooks |
| 369 | configOrQueryOrCollection.startSyncImmediate() |
| 370 | collectionRef.current = configOrQueryOrCollection |
| 371 | configRef.current = configOrQueryOrCollection |
| 372 | } else { |
| 373 | // Handle different callback return types |
no test coverage detected
searching dependent graphs…