Fork me on GitHub

Hi there. Is there a way to configure storage strategy in fulcro, i.e. where all the data reside? I'm looking for a way to persist data between page reloads, and wondering if this is possible without me having to manually save after every load or mutation. Thanks in advance.


So i haven't done this and I'm just speculating right now: In theory you could to the the app atom and then perform your logic in there. This way you wouldn't have to modify anything.


I wonder if this is something Pathom's cache/`core.cache` can be used for


As far as I can tell, this is for server-side only? I'm looking for a more frontend-oriented solution in this case 🙂


But thank you for the link, I'll prob use it as well on the backend.

👍 1

@U012ADU90SW Thanks for the suggestion. I'll give it a spin!

Jakub Holý (HolyJak)16:03:07

An atom watcher is IMO a fine approach. If it is enough for you to only cache the server-provided data then you could have look at

Jakub Holý (HolyJak)16:03:21

Hi @tony.kay! I saw this comment and wonder whether you still plan to move the code into RAD proper. I also need it for my #asami DB adapter 🙂 Thank you!


I’m game, just have not had the time

👍 1

I didn’t write those exact versions, the docstrings need fixed, and we need to find the right ns for them, but the logic is reusable, so it’d be nice to get em in there

Jakub Holý (HolyJak)16:03:29

Anything I can help with?


I’m not doing antying with it anytime soon. If you want it moved, give it a go 🙂

Jakub Holý (HolyJak)17:03:58

Ok, I will look at it. Thank you.

👍 1

That crap is busted and doesn’t work in CLJS.


I’ve fixed at least 3 bugs in fulcro-rad-kvstore and konserve and it still doesn’t work


that namespace in particular has bugs


this is a patch to fix the problem where the temp IDs are not correctly unwrapped to UUIDs. And even that is a bad idea because it makes assumptions about the structure of tempids, the correct thing would be to generate new UUIDs and return the tempid->new uuid map mapping

Jakub Holý (HolyJak)13:03:08

Isnt't structure of tempids fixed? That is what fulcros tempid fn return, no? I don't think Tony will change htat 🙂


So, I didn’t write the kv-store, and have not tried it out…have you looked at the helpers in datomic-rad plugin?


Ah, I see what you’re saying…the author tested against CLJ, but the CLJS-side isn’t right…that’s probably because the code was taken from the Datomic plugin, which is CLJ only.


Unfortunately that’s not the only issue there. i’ve wasted a bunch of evenings trying to get fulcro-rad-kvstore to work as frontend adapter with IndexedDB in CLJS. Another issue is that a specific function that can be sync or async (returning a value or value wrapped in async channel) depending on store, and it’s used as if it was always sync, and in CLJS it can only be async so that’s a show stopper right there. Then the acual serialization/deserialization of UUIDs to EDN is broken due to bug in Incognito, which erroneusly thinks cljs.reader/tag-table uses strings for tag, but it actually uses symbols


All in all it makes me think that the IndexedDB provider wasn’t tested even once.


Because there is no way it has every worked with 3 bugs that each cause a total failure of the “write a new entity, read it back” user story


Perhaps @U0D5RN0S1 can comment on that. He’s the primary author.


I’ve added a comment at the top of the README making the status of that plugin a bit more clear with a warning about CLJS support.

❤️ 1

Yeah my primary goal was to get the RAD Demo going, which is CLJ only. It worked well for me. I was encouraged to do the CLJS (which uses core.async) as well. But indexedDB was so terrible that I just left an alternative front end ( to demonstrate the problems as clearly as I could. If you hook that one up (by referring to the -2 version rather than the landing_page.cljs version) then there's a series of buttons with output going to the browser console. In general I very much tried to follow the way the Datomic plugin did things, and as you can see I 'code documented' all the duplicate functions I had to use in a ns called 'duplicates'. Of the three bugs that you found @U66G3SGP5, is it possible to demonstrate any of them by using the RAD Demo? If so then that would be a cause for concern, as this library doesn't really make any of its own decisions.


Previously with defui you could create inner functions (like you would with a class), that could render things, onClick etc.. similar to how its done in React. Is this something you can do with defsc also?


You mean the very old version of defui, which was protocol based?

👍 1

so the :initLocalState is called like a constructor, and you could put methods on this . That’s kinda yucky. Such methods never could close over state in any way, so you can always write them as fn outside of the class. If you want something truly local you could: 1. Put them in component-local state (e.g. :initLocalState). 2. (preferred) Use react hooks.


(defsc C [this props] {:use-hooks? true} …)


(hooks/use-callback …)


Hooks are really pretty nice


:thumbsup: hooks are definitely nicer


but yes, we are still on that super old defui - trying to migrate everything off now to defsc and have some components that use that old react style of having various functions inside the class. I’ve been just moving them out into smaller presentation functions/components, but wasn’t sure if there was some other way


Thanks Tony!


@tony.kay any ideas on what the equivalent for defsc would be for something like this?


(defui ListingTitle []
  static ISearchColumn
  (column-name [T _] "TITLE")
  (es-sort-fields [_ _] [:title])


Oh wait I think I found it in the docs:


(defsc MyComponent [this props]
   {:protocols (Object
                static css/CSS
                (local-rules [_] [])
                (include-children [_] []))
   (dom/div ...))


Jeez…I didn’t even remember that was there. That’s also an answer to your other question…..


Can’t wait to clean up all this old stuff 😅


hm…no, protocols isn’t there anymore


what version are you porting TO?


you might be doing stuff that is still going to require a second pass


hopefully anything above 2.5.9


Is there an alternative to what I have that would work in newer versions w/o having to rewrite the way all of these work?


Fulcro components are no longer protocol-based.


The CSS stuff uses a newer version of that lib, that just uses plain keys in the options map


ok bummer, yeah I have a ton of stuff like this:


(defui ListingHost []
  static ISearchColumn
  (column-name [T _] "HOST")
  (es-sort-fields [_ _] [:ownerFirstName :ownerLastName])

  (render [T]
    (let [{:keys [ownerFirstName ownerLastName ownerId ownerAvatarId]} (get-computed T)]
        (avatar-card T ownerId ownerAvatarId {:first ownerFirstName :last ownerLastName})))))


Is as of Fulcro 3 the components are just low-level js functions. There are no types/protocols/etc. This helps with things like dead-code elimination, and also normalizes things. The options maps is completely open, meaning you can add any key to it you want (preferably namespaced) to have any meaning you want.


So, you can put things like :es-sort-field on there, and the use component-options on the class OR instance to pull it out and use it.


This is how RAD works, and it is a thing of beauty.


So, you can just write some kind of wrapper helper for your “protocol” functions, which are tied to a ns, right? You could make es-sort-fields be a normal function in the ns where you used to declare ISearchColumn


and it does: ((comp/component-options this :es-sort-fields) this args)


with proper nil checks and such


I think so


let me give it a spin and see if I can things working


(defsc ListingHost [this props]
  {:es-sort-fields (fn [this args] [...])}

(defn es-sort-fields [this props]
  (when-let [f (comp/component-options this :es-sort-fields)]
     (f this props))

💡 1

ah interesting! Ok let me try to get this going


thanks again Tony


sure, where that last function will accept this OR ListingHost


it’ll work on both in Fulcro 3.x


you’ll see that the new localized dom lib uses this exact pattern


gotcha, but I will first need to be on 3+


I would not bother porting to 2.x…you’ll still be missing out on a lot of good stuff


and you’ll have to redo a bunch of work because defsc evolved slightly, as you’re seeing, from 2