Fork me on GitHub

Hi all, is there an idiomatic way to change the route (to one that isn’t the default) while building the initial state for SSR?


I’ve tried modifying the ::dr/current-route of the relevant router, but that alone doesn’t seem enough. It appears I need to modify the queries as well, but when i use set-query* I end up with transit errors about the anonymous functions in the metadata.


I would initialize the entire app and run it headless, and use the change-route function


ah, so functions in the metadata…that may need some work


I don’t remember putting functions in the metadata…oh…the components are metadata. I thought I changed that to their kw names in the component registry


So, if that is the case, it’s a bug…the fix is to change the dynamic query system to use the component’s key in the registry instead of the component itself…I thought that was aleady done


@U0BR5D7A6 Yeah, line 829 in components.cljc…it is still doing it the old way 😞


it isn’t that hard to fix…basically anywhere the component bit is used in the metadata needs to change to using the component registry key (which is a keyword)


An alternative is to do this: 1. Do NOT send initial state to the client. 2. Make an “initialize based on route” function 3. Render that on the server 4. Start the app and initialize normal state on the client, but DO NOT mount it yet. 5. Run (2) on the client 6. Mount the client with hydrate Then no initial state serialization is required.


I’ll open an issue on dyn queries

👍 4

@U0CL8APJ5 you were looking for a Fulcro task, I think…any interest in this?


yes, I am interested!


great, hit me up if you need help understanding it…it really is just finding all the spots and changing the code to use keywords


and testing it all, of course…but any program that uses things like dynamic routers should fail pretty miserably if this is broken


Thanks guys! 😅


I’ve tried modifying the ::dr/current-route of the relevant router, but that alone doesn’t seem enough. It appears I need to modify the queries as well, but when i use set-query* I end up with transit errors about the anonymous functions in the metadata.


my fulcro-inspect chrome extension just suddenly stopped loading with no significant change in my project that I can figure out. Any tips for how to troubleshoot why it’s not loading? I deleted .cp-cache .shadow-cljs folders and my JS build target folders and restarted the build.


I had the same problem yesterday


@thosmos does your extension have a “Settings” button?


my extension doesn’t have a “settings” button, but on the extensions list there is a “Details” button


ok, so you did not get the update


and the code in Fulcro really didn’t change in a way that should break it…


is it maybe a problem related to a new version of Chrome?


there is a new version of inspect coming out, but we cancelled the release when I saw that problem


I’m trying to find out if maybe it got released


or, perhaps it is on the client side of Fulcro…in which case rolling back to 3.1.4 or earlier might fix it


oh, hmm, it says it’s version 1.0.17 from Nov ’19


I am running fulcro out of a :local/root repo


ah, so latest source?


just weird that it was running fine and then suddenly stopped


try checking out an earlier version…


@tony.kay I canceled the publishing after you reported the issue, its not moving forward


I wonder if we broke it in F3 in general though


@thosmos I heard that happening to a lot of people before, usually re-installing the extension fixes it


since the client is in Fulcro now


not in inspect


ok will try re-installing


If you can isolate it to either a reinstall or the Fulcro version (latest vs 3.1.4 or so) that would be really helpful as well


question about dynamic router and sync the URL, how you usually update the URL in response to a change-route? there is a hook for it, or you change the URL first, detect that and then call change-route?


DR has nothing at all to do with browsers


@wilkerlucio I’m using pushy and have it detect the URL change and then call change-route from its handler (which I got from the F3 videos)


it can be used in native, etc.


it is purely concerned with changing the UI


think of it like union router changing an ident…that is all it does


I understand they don't have a explicit connection, but as an app developer I'm trying to understand the best hooks/places to connect them


I have no opinion, because I have not really done it much 🙂…I’m not a fan of bookmarking stateful applications, but I do understand the need.


@thosmos thanks, I was aiming for that direction, just wanted to confirm if this is a sound approach that people tried before with this


@tony.kay in my case its important, sharing permalinks is a important feature of the app I'm working on


(defonce history
    (fn [p]
      (let [r-segments (vec (rest (str/split p "/")))]
        (timbre/spy :info r-segments)
        (if (seq r-segments)
          (dr/change-route SPA r-segments)
          (dr/change-route SPA ["main"])))) identity))

(defn start! []
  (pushy/start! history))

(defn route-to! [route-str]
  (pushy/set-token! history route-str))

👍 4

so I use (route-to! "/full/root/path")


which is straight from Tony’s F3 videos


no idea about query params to represent stateful options though, as I haven’t crossed that bridge yet


re-installed inspect extension and restarted Chrome and it’s working again …


This is the fulcro commit I’m on (3.16)


let me know what you find…reinstall may just fix it


yes it did just fix it


no clear clue as to any thing that caused it


perhaps that is what I was running into when I was testing the new version…I’m using the new version from a local build today and it is working so far


I have a form component that I’m using both for editing new and existing things. In the various field onChange handlers I have (fs/mark-complete! nil field-key) so when loading the existing thing those get called and it appears dirty even though it’s not. Any advice for how to do that better? I’m thinking of having a :ui/loaded flag in state that prevents the mark-complete! until after it’s loaded? reasonable approach or is there a better way?


Follow what I’m doing in forms in RAD.


ok I’ll take a look (I was thinking I should do that while writing my question 😉 )


So, I just refactored RAD to be MUCH simpler (and easier to use in existing apps)


The forms stuff is pretty free-standing, and uses the route will-enter and will-leave to do pretty much everything


(start a form state machine, etc).


and then the route itself is ["route-prefix" :action :id]


so ["customer" "create" "ffffff-fff-ffff-ff"] causes the state machine to use tempids on the form


and ["customer" "edit" "some-id"] is edit


you specify the route prefix as a config on the form component


I’m adding relational support today, and there is very limited form field type support so far


but it is SUPER fast to get stuff going…I’m pretty excited

🎉 4

in my case I have a parent comp that is the route target and the child is the form comp with :form-fields I assume it’ll be obvious how to pass through whatever is needed


I just added 4 entities in like 10 mins, and other than the ref stuff it all “just works”


routing composes


but maybe if this just works I’ll collapse it into one component. One reason I have 2 layers is the parent loads lookup tables for dropdowns, etc


["a" "b" "customer" "create" "tempid"], etc.


I’ll take a look


but RAD isn’t complete enough to use just yet…have not considered passing data from UI separate from what a route might use


I ran into some weird build errors when looking at RAD, and I have a rough draft milestone to deliver on Fri, so I skipped it for now. I think in the long run merging with RAD, at least in part, is gonna be the way to go. But for now I just need to get something working.


my problem was an order of operations error. I fixed it by adding the form-state in the post-load-mutation, whereas before I was adding the form-state to the small bit of props I had followed by a full load of the entity, so anything new triggered the dirty flag.


oh, I did not mean RAD was usable in an application


I meant to look at the state machine and macro as source


@thosmos I’ve had similar concerns and eventually came to a mental model which worked in all my cases so far, but is pretty opinionated: 1) no field => input is disabled 2) nil-valued field => input is enabled, but the value does not conform to spec, so user needs to enter smth 3) non-nil-valued field => input is enabled and its value validity is determined by spec; then you initialize all the missing values in pre-merge with nils or whatever suits for defaults, and you’re also adding form-state in pre-merge, so there might be nowhere to mark-complete before the load and furthermore you’re in control of everything that said, if your problem is pretty much solved by :ui/loaded and you need to 🚢 soon, i’d go with that. there’s a lot of caveats when implementing forms...


@tony.kay I understood you meant just to look at the source, but it usually helps me understand it more quickly when I can play with it in the demo


@UDQ2UEPMY thanks for the tips, adding to my notes for the future!


Is there .mobi version of Fulcro Book?


Or anything Kindle-friendly?


the book is in asciidoc. Download source and use asciidoctor to convert it to whatever you want (assuming there is a plugin)


In case I'd do that, should I share it somewhere?


Which branch I should use to keep in sync with official book?


I don’t tag that repo or anything…just make changes and publish


@thosmos @tony.kay a simple implementation without adding external deps (using Google Closure Library):

(ns url-routing-with-closure
  (:require [ :as gevents]
            [clojure.string :as str])
  (:import [goog History]))

(defonce page-history
  (doto (History.)
    (.setEnabled true)))

(defn listen-nav-change [f]
  (gevents/listen page-history "navigate" #(f % (.-token %))))

(defn change-route [path]
  (.setToken page-history (str/join "/" path)))

(defn change-route-from-nav-event [app]
  (fn [_ token]
    (dr/change-route app (str/split token "/"))))

👍 12
❤️ 4

I would just add in one more layer: a function that translates the URL to the vector instead of split


then you can do route aliasing


like / => /main-page


also, did you see the new dr/path-to…much better to use that in real code


makes things navigable


I'm using this in combination with path-to


(change-route (dr/path-to SearchPage))


yeah, I agree we inprove on the aliasing, that's was just initial URL connection setup, we can go crazy from that 🙂


I guess we could add that to Fulcro since ppl inevitably ask about it

❤️ 4

you want to make a PR, @wilkerlucio? Some new ns, since we cannot pollute dr with and History


I would like to spend more time experimenting with it before adding to the library, find a good API first

❤️ 4

@wilkerlucio that’s dope, real handy when you need full control, esp so when making Web+React Native in one app (because you can’t just require say accountant in RN, it would crash the app, so you fork it anyway) jfyi smth like accountant also allow for <a href> links to both be routable without page reload and to be a real links in the sense that you can Cmd+Click to open it in a new tab, which might be critical for many apps (as it was for us), but of course that’s just one more fn

👍 4

hello everyone, as you may know already, the new Fulcro Inspect on electron has a nice new DB Explorer tab, currently its not available on the chrome that's published, the reason is that Google is now making much harder to upload extensions, in the past I could upload and have it updated on the store in about 30 min, now it may take weeks (requires manual checking, because the extensions needs some extensive permissions to work on any page). Given that, the deploys now need to be more careful (if we get a bad version out, it may take a while to get it fixed), also because of that I like to encourage you to build and install the extension yourself, this way we can have more people trying it before the store release, if you wanna do so you can find instructions at If you do that now you can use the DB Explorer right now! 🙂 Cheers!

👍 36

having an issue getting a component to refresh after a load! the component itself queries for a link, and I’m adding a refresh option to the load to update that link. for some reason, although my app db is updated the component doesn’t seem to be re-rendering. any high level ideas about how I might be approaching this incorrectly?


is your refresh referring to the link or to a key in the parent that contains the link?


the link as in the db


assuming if the link in the query looks like [:my/thing '_] the options map in my load! would look like {:refresh [:my/thing]}


does the component have an ident? if so, what if you use that in the refresh?


yep, has an ident and that does work. unfortunately quite a few components are changed by the data I’m loading, making sure each has an ident and listing it in the refresh is a little unwieldy


Try switching to keyframe renderer, to see if that solves your refresh issues. Then you can optimize it with keyframe2 renderer.

🙌 8

yep that did the trick. really appreciate the help y’all

👍 4

yeah I use keyframe2 as well