Fork me on GitHub
#fulcro
<
2022-08-30
>
Mark Wardle11:08:38

Hi all. I have a style question in relation to routing. I am trying to nest routers, but keep getting into difficulties - nil idents and having to route to a known leaf node from a component which really shouldn't need to know. Passing data through a router to child routes has been tricky. It occurs to me that I can probably achieve the same functionality by avoiding nesting and having a flat but wide routing structure, because I can make the UI appear to highly hierarchical, and consistent, simply by re-using components. I'd be grateful to hear opinions!

tony.kay19:08:06

Technically I’m pretty sure your UI routing is working. I’m guessing you’re trying to maintain URL/UI synchronization? The dynamic routing ns is meant for use in ANY env (not just web), so if you’re trying to deal with the URL, you must add in wrappers that do that part for you. When you say “routing to a known leaf node from a component that should not need to know” I’d say then that component should not be responsible for that route, unless you mean there’s some parent that is common between the two, in which case you should be using relative routing. The composition in dr is designed as much as possible to compose and refactor cleanly. A link to some “global location” in the app generally needs to have “global knowledge” (even if it has to pull that information from the state atom). Sync with the URL (again a global concern) is also outside of the bounds of the built-in behavior. I think you’d have to be specific with single examples to get better feedback. The design of Fulcro’s dyn routing has different design goals (and also in some cases purpose) that most other front-end systems, where the only concern is putting UI on the screen based on a URL. Fulcro’s dr is about changing the query graph dynamically, composing app elements without having to have a global routing definition (redundant), and being UI agnostic (Native, etc). IMO, if you generally have global routes that you need to direct to from a nested component, then it is best for them to be very near the top of the graph, and (where possible) should not be nested in things that require parameters in order to be functional (unless you’re willing to make that data well-known for these children to use). If you do need to nest things (e.g. select which top-level thing, like account, and then route between nested things) you will need to make a routing wrapper that knows where to find the currently-selected top-level thing, and will plug it into the routing parameters automatically as you change routes (as a default that can be overridden by incoming user paramerters):

(defn my-route-to! [this target params]
  (let [state-map (app/current-state (comp/any->app this))
        selected-thing (:selected-thing state-map)
        route-params (merge {:thing selected-thing} params)]
     ... real routing ...))

tony.kay19:08:35

Then in the will-enter of your parent (the selected thing) be sure to transact the :selected-thing into your app state (I’d use the new support for blocking transactions so you can compose this well). See dr/route-with-path-ordered-transaction

tony.kay19:08:54

@U0522TWDA might be something of interest for you to add to tutorials?

💯 1
Mark Wardle21:08:38

Tony thank you very much for your reply. I understand. I previously misinterpreted routing to be a UI concern when in Fulcro I see it is a data concern. Therefore I can see that multiple top-level routes are better than lots of nested ones, particularly as I have been thinking I should use parameterised routes. Actually I also removed all HTML5 routing to keep things as simple as possible. But on reading your replies, I'm almost tempted to remove my route parameters and have state only in the normalised db and keep the UI entirely functional, and easy to reason about. I think part of my issue has just been making assumptions based on what I've done in other frameworks etc, so I am unlearning first :) thanks again.

tony.kay21:08:42

sure. Breaking patterns is a definite weakness to trying new things 😜

👍 1
janezj21:08:10

In my case com.fulcrologic.rad.routing/route-to! solved all my routing problems. plus wrapping nested routers with computed props. (kudos to @U0522TWDA),

👍 1
sheluchin12:09:06

Thanks for that lengthy explanation, @U0CKQ19AQ. It really helped me understand Fulcro's approach to routing and the separation of responsibilities between routing and URL handling.

👍 2
tony.kay18:08:24

Update to Fulcro RAD Datomic plugin. Improves support for using tuples to get fast server-paginated reports with the latest RAD.

Mateusz Mazurczak19:08:45

Hi, I'm a little bit lost in fulcro and I would need someone to go over my repo (not much code) and review it. Because I don't think I'm doing it right. If someone can help me, please reach out to me under this message or pm me with the price for it. Here is the repo: https://github.com/Kaspazza/clj-world/tree/main/src/main/app I can also record a video/do a meeting and explain the code.

Mateusz Mazurczak19:08:45

It's 3 files, client.cljs (root) and two views ui/categories and ui/lesson

tony.kay22:08:52

Did you try the YouTube tutorials, or any of the other resources in the channel topic? (Book, tutorials, etc.)

Mateusz Mazurczak08:08:35

Yes, I've watched the tutorial, read the book, did the fulcro exercises (on the span of last two years I did this multiple times), but I feel like it's completely different experience than building the app from scratch (at least this small app that I've build). So I just want to pay someone to look over those files and tell me what I did wrong and how it's supposed to be.

Jakub Holý (HolyJak)09:08:36

I can help you with that. My price is at http://holyjak.cz/holy-dev.html Looking briefly over your code, why does Root include query for categories and lesson? It should only have one for the router b/c it is the only thing it instantiates. This https://blog.jakubholy.net/2020/fulcro-divergent-ui-data/#_inserting_a_stateful_ui_component_between_a_parent_child_entities explains how the router fits into the data tree. For initial-state it is shorter and has better error checking to use the template form. Why do you use the fn one? See the TIP under https://fulcro-community.github.io/guides/tutorial-minimalist-fulcro/index.html#_components_initial_state