Fork me on GitHub

I made a blog video on the new work around hooks and easier APIs. Have a look and see what you think:

❤️ 30
fulcro 21

do you think that would be possible to use completely without react? so that the "definition" parts all stay fulcro only and then there iis just the choice of either using react hooks to hook into the DOM lifecycle or using my shadow-grove stuff instead. it looks like that should work right?

(def User (fulcro/something [:user/id :user/name ...]))

(defc ui-user []
  (bind data
    (fulcro-grove/use User {...}))
    (<< [:div (:user/id data)])))


currently its all coupled to react hooks but it doesn't have to be right?


probably not a goal for now and thats fine but it would be neat if at some point I could just leverage all the work you've done on fulcro and just use it without react 🙂


this looks really cool, and seems like it's trending with some of the experiments I've been doing myself outside of Fulcro with my EQL lib and React wrapper However, I still find the Fulcro API surface overwhelming. There's still a ton of "Fulcro take the wheel" in what I'm seeing in this video, which makes it incredibly daunting to adopt e.g. at work where I would be much more inclined to use something that has been production tested, rather than my hare-brained experiments 🙂 Sort of in line with thheller, I would like to see Fulcro continue to be boiled down to less and less UI stuff: create an entity, instantiate an entity, fetch an entity, listen to changes. As someone who's very very familiar with React and building UIs, but not super familiar with Fulcro, there's so much Fulcro on the screen that it's difficult for me to figure out what's essential to what I want to do - basically fetch data from Pathom and store it in a normalized db - and what's useful for Fulcro apps that are bought into Fulcro's way of organizing a project. I hope this is useful feedback. 🙏:skin-tone-2:


@U05224H0W Yes, this decouples it from React. I’m using hooks as a way to get to the side-effects, but if you look at the implementation, there’s no React required. The “render listener” happens after transactions. I’d be happy to finish disconnecting it cleanly from React if we find any other hard dependencies…really just the mount and initial root render are tied to react.


oh that is good to hear. I'll check the raw-components stuff you have and see if I can port it.


@U4YGF4NGM Fulcro does almost nothing with UI and React. There’s a DOM ns and render plugins. The vast majority of the work is around the data model management, network interaction, transaction processing/ordering, remote interaction. Yeah, Fulcro takes the wheel on all that stuff. That’s the design. I saw your experiments. More power to you if you see a way to distill something useful out what is here. The real complexity in real distributed apps is non-trivial, and therefore not small. That said, Much of Fulcro (UISM, Dynamic Routing, DOM, Form State) should be viewed as optional things you can use, not things you must use. I don’t have time to manage all of those bits as a separate project/lib/repo/doc…so they are combined together…but they truly are pretty separate.


@U05224H0W yeah, you just need some way of dealing with “lifecycle”


and getting the render update to the right place on the screen


but the render listener approach just basically gets you an event you can use to pull data from the db after transaction steps (and network results). So, there’s no need to even embed it specifically in the UI layer. Fulcro has basically been this way for most of the 3.x lifespan, BTW. Most of the internals are usable in a completely headless way, and the rendering has been pluggable as well. I just haven’t done much documentation around how you get truly away from React, but React really isn’t coupled in very many places. application.cljc does not require it, though components does. but that is due to defsc making react components. So, at the moment you’d get some React “bloat” in your build, but you can completely avoid calling any functions. The add-hooks-options! actually has no real ties to React, and in fact just sets up a function so it responds properly to Fulcro requests for things like get-query and such…so, it could even be renamed add-pure-function-options! or something.


You could redirect the React requires to a stub file and avoid the bloat, and I think you probably know how to do that 😄


yeah I glanced over the code and I can easily replicate what the react use-state hook does as well as the use-lifecycle


I'll get back to you when I have questions


excellent. looking forward to what you come up with


I have a post-load mutation. The load! retrieves a list of people from the server. In the post I want to set the first person in the db as a selected-person in a different component. I’ve tried a few different options and none seem to work.

(defmutation post-load [_]
  (action [{:keys [app state]}]
    (log/spy @state)
    (let [person (->> @state ::person/id vals first)
          id (-> person ::person/id str)]
      (swap! state merge/merge-component person-ui/PersonRoot person :target [:component/id ::person-ui/root :ui/selected-person]))))
;(swap! state targeting/integrate-ident* state [::person-model/id id] :target [:component/id ::person-ui/root :ui/selected-person])
;(swap! state merge/merge* [:component/id ::person-ui/root :ui/selected-person] (log/spy person)))))
;(routing/route-to! app tabs/ProfileTab {::person/id id}))))


I’ve also tried

(swap! state merge/merge-component person-model/Person person :target [:component/id ::person-ui/root :ui/selected-person])
which is the component that matches the Person query in the root component.

Jakub Holý (HolyJak)07:03:19

Merge doesn't make sense to me since you do not want to insert data into the DB, only add an "edge" / pointer to existing data. How does the targeting call not work for you? Also notice swap is just a map. You can change it manually: (assoc-in state [:component/id :person-ui/root :ui/selected-person] [:person/id <the ID value>)


@U0522TWDA is there an idiomatic way to add an edge?


Btw I’ve been using Fulcro troubleshooting and it’s great.

❤️ 3
Jakub Holý (HolyJak)12:03:11

The targeting namespace but I saw you already tried that... Just wanted to point out it is just data, no magic


@U0522TWDA targeting ns worked in the end.


And the swap! that I would have expected to work.


Looks like the named option is :replace not :target with merge/merge-component.


I’m trying to use a component that joins with a union component and hitting this error I’m attempting to do something like

(comp/get-query (add-extra-params ns/OtherComponent))
I’ve also tried manually building the query and encounter the same error. Do all union joins need to be backed by their own component?


Having a look at the code this seems to use dynamic queries which I haven’t touched at all so I’m leaving this for now and just lumping all the query params on the ‘base’ union component


I’m aiming for a sort of ‘higher order’ union component. I’ll leave this until I’ve internalised dynamic queries


yes union queries need their own component.


Thanks 👍