Fork me on GitHub

@mss A router is really just a very simple pair of components: one to track the route, and one to deal with the union query. The base set-route function can be composed into mutations of your own, and can target a single top-level router. Interpret “parameters” however you want.


@timovanderkamp So, the merge behavior should depend on the query. If you query for the same stuff, then the behavior is to overwrite anything that was queried for. This is so that disparate queries coming from different branches of your UI don’t misbehave. You’d have to give more detail for me to say anything about it being “OK” or not. Another thing that is supposed to happen on a query for the same top-level thing is that the transaction should be split into two loads. If that isn’t happening, then the return value (which is a map that can only have one value at that key) will end up with whatever the server merged them together into.


I’m not seeing how a “workaround” in this case even works, since the data was lost at the server


so perhaps I’m not understanding your problem


i've wrapped the dom construction functions with some assertions that check if the attrs argument is a js object, this catches some errors earlier, (mistakes like passing {} instead of #js {} to dom fns)


@tony.kay would you consider a PR that adds these assertions to fulcro's dom functions?


@chrisblom that seems ok. Eliding asserts on advanced compile keeps them from being performance problems.


how’s the dev experience with it? Do you get a decent error that can be traced?


yes, i get a stacktrace with the line where the dom fn is called


do you prefer assert or preconditions?


sorry, missed the thread until now. assert is better IMO because it includes a more user-friendly message


just a follow up to my routing q from earlier: I’m having trouble conceptualizing how the set-route function would work with my Project example above, and am generally a little confused by gluing together the different pieces of routing machinery. afaict, and maybe I’m missing something – but unless the key in your initial state that corresponds to the id in the route tree ident declaration for that route is known at load time, you won’t be able to load that route. in my example above, because Project’s :route-id is nil via the initial state declaration, the route ident that the router is trying to match on is [:project nil] when looking for [:project :param/route-id]. trying to transition to [:project 4] won’t work. per this example using the dynamic router – ( – the actual idents of the loaded routes are static. the idents themselves don’t change. is there a mechanism for dealing with routes where the idents themselves are changing? should I just use a dynamic router and load a route for every single Project post data fetch? am I just missing something altogether about how this works?


correct, you need to use a post-mutation on your load to do the routing


and inside of that post mutation, you’ll need to be able to figure out the ident of the target


(load :root/project Project {:post-mutation ...})


dynamic routing is mainly about loading code modules and routing (though it can be used differently, that is the main purpose)


where the routing tree declaration for that route would look like (r/make-route :new-user [(r/router-instruction :top-router [:project :param/project-id])]))?


you don’t need a routing tree if your routes are flat


and you don’t need param substitution


you’re making it a lot more complex than it needs to be


yeah I had a feeling that was the case 😭


you have a project: It has an id


If you (load :root/project Project) then your app state will contain {:root/project [:project/by-id 3]} or something like that


a mutation can read that, and use it on set route


(let [target (get @state :root/project)]
   (swap! state r/set-route :top-router target))


mix and match from there…you could scan a database table, you could integrate the thing using :target, etc.


for that matter, you could target it at the router’s current route 🙂


oh interesting. didn’t realize the routing tree/entry was optional, makes sense how to integrate it from there


and it should normalize and set the route all at once, since all set-route is is a function putting an ident in state, and the router has the query for normalization


tree is just about helping you translate the concept of a single page to a group of routing instructions


you could just as easily write that as a bunch of set-route calls in a single mutation


Look at the URL, derive your parameters, figure out your idents, and set-route on affected routers


it’s just for convenience


very interesting, that makes a lot of sense. really appreciate the help


sure…I need to do something about that chapter, and possibly the API. It seems to create more confusion than I would expect 🙂


did you watch the YouTube video on routing?


unfortunately no, and I probably should have. just working through the book and referencing as I build a toy application


part 10 I think


watching a few of the videos is highly recommended. I think it gets you over the “hump” and prevents you from making things more complicated


yep I found the video. will definitely dive in


thanks again


with so many new concepts, and our shared history of js being “hell”, we tend to think “it’s gotta be harder than that”


Features like routing and forms in Fulcro should be thought of more as “things that save me a little typing” on top of things that are tedious, but relatively simple.


absolutely. for me the most difficult part has been the shift to the graph-based data resolution model. I’m coming from a very imperative (redux) vanilla js background for client work with some clojure experience on the server. figuring out what queries are used where and how they’re manipulated is difficult mostly because the graph based approach feels so radical. multiple new mental models to check in with and refine anytime something doesn’t work as expected


thanks again tho. really appreciate all the work you’re putting into this. really great toolset and approach


You’re welcome. Always like to hear where the newcomer hang-ups are so I can improve the docs. So, let me know once it “settles in” a bit what you think might help