-
Notifications
You must be signed in to change notification settings - Fork 49
live query docs #242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
live query docs #242
Conversation
|
@tanstack/db-example-react-todo @tanstack/db
@tanstack/electric-db-collection
@tanstack/query-db-collection
@tanstack/react-db
@tanstack/trailbase-db-collection
@tanstack/vue-db
commit: |
Size Change: 0 B Total Size: 38.6 kB ℹ️ View Unchanged
|
Size Change: 0 B Total Size: 1.05 kB ℹ️ View Unchanged
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it!
|
||
### Convenience Function | ||
|
||
For simpler cases, you can use `createLiveQueryCollection` as a shortcut: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we want this? We explicitly went down the two function calls as a way of being explicit about how collections work & I'd rather keep things consistent — people can certainly add their own convenience functions if they'd like
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thinking here is that this could be the exception to the rule. Users will be very regularly be creating liveQueryCollections outside of components, in loaders and other places, and if we don't provide this wrapper they will after a while get frustrated and make it themselves. The intention is that it exposes the same api as the useLiveQuery, you just use the callback to build your query, so moving between the two doesn't require any different structures in your code.
This is a strong opinion (I would expect it from the lib), but but weakly held - if you felt equally strongly that we should remove it then let's do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I don't feel that strongly against it 👍 so let's keep it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@KyleAMathews on this, we are likely to want a createLiveQueryCollections
(plural) that can return multiple multiple collection from a single query pipeline. Thats where the liveQueryCollectionOptions
falls down, it imposes a 1:1 query-to-collection relationship. We certainly keep it, but it's worth considering what this looks like when we move on to that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great stuff!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome stuff. Fantastic reference, lots of information, very clear and well organised.
```ts | ||
import { createCollection, liveQueryCollectionOptions, eq } from '@tanstack/db' | ||
|
||
const activeUsers = createCollection(liveQueryCollectionOptions({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was surprised to see the use of createCollection(liveQueryCollectionOptions({
in most of the code examples.
So far, most of my use of live queries has been in a component context with useLiveQuery
. Below later on you switch to the more convenient createLiveQueryCollection
. And then also introduce the Query
class.
Using createCollection(liveQueryCollectionOptions({
is a lot of "collection" for creating a query.
|
||
### Using liveQueryCollectionOptions | ||
|
||
The fundamental way to create a live query is using `liveQueryCollectionOptions` with `createCollection`: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the existing PR discussion below. To share my viewpoint (which is perhaps slightly fresh / less deep in the weeds):
- if we have createLiveQueryCollection then that is simpler for examples (that don't need the extra flexibility) than the
createCollection(liveQueryCollectionOptions({
- the most common starting points to use live queries is in component context, with useLiveQuery
I think this section Creating Live Query Collections
all really emphasises that live queries are collections. I'm not sure this is necessary. It's like "yes a live query is a collection but it's also a live query". Like the page is called "live queries". Could this section be "Creating Live Queries" and start with a "live queries can be created and used in a few different ways. The most common is in a component using useLiveQuery but they can also be created standalone using createLiveQuery and composable using the lower level Query builder".
Note my dropping of the Collection suffix from createLiveQuery. Then still explain that a live query is a collection and show that the longer createCollection(liveQueryCollectionOptions( is equivalent with more flexibility. But then the examples can more clearly generally use createLiveQuery
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another perspective on this is that if live queries are just collections then perhaps we should be talking about querying collections, not about live queries. I.e.: either a live query is a thing and a collection is a thing. Or they are one thing and collections are just queryable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, having leand into the concept that a "live query is a collection", I fear we are going to break that distinction more as we expand the live query capabilities.
We currently have this 1:1 relationship of live query to collection but thats not going to be the case soon.
This is a common pattern that I think we will want to support:
const { totalCount, pagedResults } = useLiveQuery((q) => {
const baseQuery = q
.from({ issues: issueCollection })
.where(({ issue }) => eq(issue.projectId, 123))
.where(/* more complex expressions from UI filters */)
const totalCount = baseQuery
.select(({ issue} ) => ({
count: count(issue.id)
}))
const pagedResults = baseQuery
.orderBy(({ issue }) => issue.data)
.limit(30)
return { totalCount, pagedResults }
})
// Render the total results count in a header, and then the paged results below.
// (note the I have some ideas now to reuse the same query for paging through
// results, but thats another thing later on)
With that I feel we need to more away from the 1:1 relationship.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't totalCount and pagedResults both be collections? We're not breaking the connection if useLiveQuery gets more complex.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, they are still collections. However rather than a live query collection being constructed by using liveQueryCollectionOptions and passing that to a collection, we have to have a factory that takes a query and returns 1+ collections.
It's no longer Collection passed Options, which are in turn passed a Query, it's a Query processed to output multiple Collections.
There are lots of nuances that will need solving, such as the lifecycle of the Collection no longer being 1:1 with its query as that query may be being used by multiple collections.
|
||
Live queries are just collections that automatically update when their underlying data changes. You can subscribe to changes, iterate over results, and use all the standard collection methods. | ||
|
||
## Table of Contents |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think another section or aspect that's maybe not currently covered in this guide is query dependencies.
When queries are defined/derived from other queries/collections then they automatically update when their source queries/collections change.
When queries are defined using JS variables then their definitions do not change. In a component context, this is addressed with useLiveQuery where you pass a dependencies array.
The mechanism for handling dependency changes in the latter case is much more blunt than in the former.
I think it's worth outlining how this stuff works. Perhaps the meat of the usage with dependencies belongs to the specific framework docs. However I think the principle should be established here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure where best to place info on the deps array, but suspect in the React docs. Vue for example should not need the deps array and its not part of the apis discussed here. I do agree is complex and maybe needs highlighting more.
I'm merging this now as there is useful information, we can continue to iterate in further PRs |
See here: https://github.com/TanStack/db/blob/samwillis/query-docs/docs/live-queries.md