Guidance on how to compose and lazy load queries in TCA features #260
-
|
This is somewhat related to #47 but a bit more nuanced. Core questionsI'm trying to understand
ExplanationLet's say I'm building a feed reader. I want to create a list of all posts, but I don't want to query all post content all at once. Instead, I want to create a list view that queries all the post ids and then have an item view that handles querying the post itself and holds some other view specific state. There are a couple of reasons I want to do this:
The issue I have is that, as I understand it, the primary guidance for TCA is that a parent should hold its children's stores. However with my current understanding of how to use SQLite Data, that when I create a store for each of the children, it will immediately execute a query even though the view is not visible. Things I've triedRegarding how to coordinate the query vs the child state, in my actual code, not my contrived example below, I currently have an For lazy loading, through some testing I figured out that I can wait to Another thing I tried was keeping the child query outside of the TCA state so it'd be tied to the view lifecycle. This does technically work but then feels like I'm doing something wrong keeping part of my state somewhere else. I'll admit, I'm still new to this so it's entirely likely I'm thinking about the whole problem wrong and the question I'm asking is not actually the one I need to ask. Can you point me in the right direction? I haven't come across any authoritative info on this topic so far. ExampleFor discussion, here's an example of the version of this that eagerly performs all fetches immediately. If you load this preview, you'll see 1000 queries because each child store immediately executes. What I want to see is that there are only a handful of queries for the items that are in the view. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 9 replies
-
|
Having modeled things this way, I recommend against it. It seems more efficient, but creating the child features, and then each of them holding an observation to the database becomes expensive. Instead, bring the parent and child features together.
Then, if you truly need pagination here's what I do:
|
Beta Was this translation helpful? Give feedback.
-
|
I agree with everything @rcarver said above. This is not the correct way to model things: @ObservableState
public struct State: Equatable, Identifiable {
@FetchOne public var item: Item?
…
}This executes a SQL query and establishes an observation of the database for every single row of your list. This just isn't going to ever be efficient, and even SwiftData would have the same problem if you used And really, I don't think you even need a TCA feature for each row of your list. The vast majority of apps have quite static content for rows of lists, and it's only when you drill down / present a sheet that you encounter the behavior that would benefit from a full blown TCA feature. And so really the parent feature should just have a |
Beta Was this translation helpful? Give feedback.
Having modeled things this way, I recommend against it. It seems more efficient, but creating the child features, and then each of them holding an observation to the database becomes expensive.
Instead, bring the parent and child features together.
@Selectionto narrow to just the fields you needForEachthose rows directly for the view.IDof the row, for examplecase buttonTapped(Row.ID)Then, if you truly need pagination here's what I do:
NSCollectionViewwhich provides that data