This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # announcements (1)
- # babashka (40)
- # beginners (228)
- # cider (9)
- # clara (6)
- # clojure (68)
- # clojure-uk (13)
- # clojuredesign-podcast (5)
- # clojurescript (9)
- # core-typed (1)
- # cursive (1)
- # duct (2)
- # emacs (9)
- # fulcro (18)
- # graalvm (11)
- # hyperfiddle (1)
- # malli (2)
- # off-topic (33)
- # re-frame (9)
- # reagent (3)
- # reitit (15)
- # shadow-cljs (6)
- # tools-deps (1)
Hi. I am going through the Fulcro 3 videos after a longer break from playing with Fulcro. I've just seen https://youtu.be/wuOnP5yufxU?list=PLVi9lDx-4C_T7jkihlQflyqGqU4xVtsfi&t=2499 that talks about different ways to load PersonDetails in a PersonPicker when a specific PersonListItem row is clicked in PersonList component. All the solutions were focused on specifying the onClick logic inside of PersonListItem which is coupling it to PersonListItem to its parent (PersonPicker). Shouldn't we have instead that callback passed as computed data (http://book.fulcrologic.com/#_the_correct_way) from PersonPicker component down to PersonList and then again to PersonListItem so these components don't have to know about how they are arranged and connected in the parent component? Shouldn't this solution also make some of the issues presented in the video automatically disappear?
Another question 🙂 this time about https://www.youtube.com/watch?v=Bistiamcz8Y&list=PLVi9lDx-4C_T7jkihlQflyqGqU4xVtsfi&index=8 and loading/refreshing data of an entity from a remote. Is it possible to ask Fulcro to load a remote data using a query that will include all the properties that are already present in the client database? The video was showing
(df/load! APP [:person/id 1] PersonListItem) and its issues. Is it possible to call something like
(df/load! APP [:person/id 1] <query for all the attributes present in the client db for person with ID1>? Would that even make sense?
Maybe I’m missing something, but the simple answer is - use the same component to do the load as you initially used to populate the database. Any properties in the database for that entity had to get there somehow - either from a previous load, a merge, or initial-state. Any of those would happen in the context of a component, so using that component to do a new load would use the same query/properties. Technically, this gives you a query for all the possible properties of an entity, not just what properties are already present, but I can’t think of a use case where that isn’t what you want (but to be fair, I’m just getting over a cold and kind of groggy today, so if you have a particular use case in mind, please elaborate). If you do have such a use case, I suppose you could implement something using dynamic queries. But that adds a lot of complexity and you’re likely wandering into uncharted territory and could run into problems (not sure dynamic queries were designed with that kind of usage in mind). So just make sure that’s really what you need - odds are there is a better solution to whatever the problem is that others have tried.
Thank you for your answer @U0JPBB10W. I was referring to the specific issue discussed in the video. Please see my comments here: https://clojurians.slack.com/archives/C68M60S4F/p1577693035147800?thread_ts=1577558891.132100&cid=C68M60S4F.
@piotrek First question: It’s hard to give a specific answer to a question like that without explicit code example (design is usually situational). But in general for components with queries it depends on the behavior. If the behavior context is very much tied to to that particular component, like change a person’s name, then it’s cleaner to invoke that mutation directly in the PersonListItem. If the behavior involves the parent context, like remove person from list, it typically makes sense to pass that in a computed prop. Regardless your business logic will live in the mutation definition and be decoupled from the UI, and that is the most important part not where the transaction invocation is defined. Does that make sense?
Thank you @U09FEH8GN. I was referring to the problems being solved in the video and I meant that particular scenario.
Second question: you can query for
['*] which will grab everything it sees but that doesn’t handle join relationships. But that only makes sense in certain contexts. It’s much better to prefer being explicit about the data needs of a component. It’s more efficient and handles joins/refactors better.
Here, the issue was that we had two different components displaying 2 different sets properties of a single identity and a refresh/load of that entity using the correct query. I am wondering what we should do in case one component (ComponentX) displays props A, B and C of an entity and the other (ComponentY) C, D, E, F or the same entity. So in this scenario ComponentY props in the query are not a superset of ComponentX props query. What should we do in this scenario? Two separate loads using each of the components queries or some other kind of load (with query joining both components queries?)?
i would prefer two separate loads for each component, that will work and make sure you have the most up to date data each time, you can show a load for the parts that are loading
and this approach is friendlier to refactoring and reuse of components in other situations
if you really need it to all happen in one load (i.e. don’t want to show a loader for the second component), then i’d call
df/load! for both components at the same time up front
there’s a slight overfetch but it’s nominal and totally beats adding a third superset component that robs you of the benefits of co-location