fulcro

Book: http://book.fulcrologic.com, Community Resources: https://fulcro-community.github.io/, RAD book at http://book.fulcrologic.com/RAD.html
tony.kay 2021-07-02T02:20:59.360400Z

The built-in renderer doesn't have the concept of hiding an entire subform. remember that RAD's model is one of gradual "outgrowth". In this case since the renderer does not support what you need, your choices are: 1. Create your own rendering plugin (based on the existing one) and add what features you need 2. Submit a PR to the built-in one. I'd be willing to add support for that on the ref attributes or maybe better as a lambda on the subforms options. 3. Add a custom ref container style. That let's you customize how refs are rendered. This is related to 1/2. 4. Take over the rendering of the form by simply giving the forms a body, in which case you can do whatever you want.

tony.kay 2021-07-02T02:21:54.360600Z

Take a look in RAD form.cljc:127, ref-container-renderer

1đź‘Ť
tony.kay 2021-07-02T02:22:31.360800Z

and its usage in the SUI plugin form.cljc line 212

tony.kay 2021-07-02T02:25:28.361Z

Items that come to mind: • Using React state for fast local updates, commonly useful for: • Using local state for things like animation control, etc. • Storing certain things in atoms for global access, such as a map from React refs to components so you can do things like manage focus or attach hovers to the DOM via external libs So, yes, there are definitely use-cases. However, if you are rendering a core bit of your application domain, you'll be better served using Fulcro for that

tony.kay 2021-07-02T02:29:05.361200Z

Making little wrapper functions to emit some (common) reusable DOM is fine. You can also use the new raw components support in 3.5 to do pure hooks-based low-level functions. I've not documented those very well yet, but the new stuff is quite powerful and less verbose. See raw-components/nc, hooks/use-component, etc. defsc gives you the rough equivalent of a React PureComponent with automatic shouldComponentUpdate, and more importantly integrates you with the graph query and data normalization...but sure, it is quite common to just write some boilerplate UI in a plain function and just call it.

tony.kay 2021-07-02T02:32:45.361400Z

I would encourage you to look at the new hooks and lightweight/raw component stuff in 3.5. Subscriptions have a lot of complexity to their simplicity, and I decided long ago that providing them "out of the box" was a bad idea...too many things to configure, opinions to satisfy. It's actually quite trivial to implement them, dependning on your requirements. The React effects hooks, combined with raw/nc and hooks/use-component can get you quite far.

tony.kay 2021-07-02T02:37:03.361600Z

I'm sure coming up with a use-subscription would take all of about 30 minutes for the base case. I've got a component I wrote for doing a dropdown that auto-loads the options that looks like this:

(defsc ProductInventory [this {:product/keys [id]}]
  {:use-hooks? true}
  (let [Inventory (hooks/use-memo (fn [] (rc/nc [:product/id
                                                 :product/sku
                                                 [df/marker-table ::inventory]
                                                 {:product/calculated-stock [:location/id :location/name :inventory/quantity :inventory/unit-cost]}]
                                           {:initial-state (fn [& _] {:product/id               id
                                                                      :product/calculated-stock []})})))
        {:product/keys [sku calculated-stock] :as props} (hooks/use-component (rc/any->app this) Inventory {:initialize?    true
                                                                                                            :keep-existing? true})
        loading?  (df/loading? (get props [df/marker-table ::inventory]))]
    (hooks/use-effect (fn []
                        (df/load! this [:product/id id] Inventory {:marker ::inventory})
                        identity) [])
...

tony.kay 2021-07-02T02:38:27.361900Z

nc lets you generate a dynamic component on the fly with auto-generation of ident based on the first ID field found in the (nested) query. It actually generates a TREE of anonymous components for normalization. Then you can hook that up with use-component to get the data from state, and use-effect to trigger the load. Generalize that and you've got use-subscription

tony.kay 2021-07-02T02:39:02.362100Z

arguments are: tree query, id of thing to load. Output is the props of the loaded thing.

tony.kay 2021-07-02T02:39:33.362300Z

use-memo is just so it doesn't keep generating new anonymous components on every render

Mardo Del Cid 2021-07-02T03:08:03.362500Z

@tony.kay The legend himself has graced us with his presence! 🙂 Thanks, Tony. I was actually looking at rc/nc because I wanted to mimic what you did with form-config-join, which uses it. Wasn’t quite sure what it did, but after your explanation I think I get it. However, I’m building a toy project first before going deep into fulcro’s internals. There are a lot of concepts I need to get my head around still. Thanks for the amazing framework, I have gone through a cycle of “screw this, it’s too overwhelming” and coming back again because all design decisions are just beautiful, every bit there that’s “hard to learn” is there for a reason, to make things simpler in the grand scheme of things… banging my head against the wall has been worth it every single damn moment ❤️

sheluchin 2021-07-02T13:16:46.362800Z

Thanks @tony.kay. I'll lean heavily towards using Fulcro except for the most inconsequential UI changes.

sheluchin 2021-07-02T13:42:35.363Z

I'm a little late to the discussion here but I would like to provide some feedback of my own. I think I'm the opposite of the case mentioned above. Instead of just copying a template and starting to hack on things, I went the opposite route and spent most of my initial time carefully studying and reviewing the first four chapters of the Fulcro book. I have most of it committed to memory, while also watching some of the tutorial videos for additional context. I haven't yet taken a deep dive on the community resources - that'll be next. I'm definitely still at the beginner/learning stage. I'm now putting most of my time into working on some personal Fulcro projects. Despite knowing the intro material quite well, things are still pretty difficult. The Fulcro model is just very different from what I'm used to, which is mostly building Django apps. My point is that - at least in my case - understanding the concepts is not easy despite familiarity with the lesson material. Studying that stuff is an essential step, but nothing really beats practice and testing your understanding. Being somewhat new to both Clojure and Fulcro, getting to the practice stage requires a decent amount of upfront work. Setting up a project and getting comfortable with the tooling takes a non-negligible amount of time. The templates are good, but I also feel like I'm missing out on some of the essential learning by relying on them before really understanding everything they do for me. Perhaps something interactive to help new users really learn the building blocks in isolation from other complexity would be useful in helping people get started? Maybe some web-based interactive tutorials that allow users to practice small pieces like setting up idents, queries, and initial states on components, and making sure they compose properly all the way to the root. Maybe present some sample source code with errors, and give users a point-and-click interface for fixing it? Not sure, just kinda brainstorming and offering my own feedback. The Fulcro community seems to be growing nicely, maybe we could consider adding such learning resources at some point.

2021-07-02T16:43:04.363300Z

this is really cool! I have try out these nc and hooks tools..

Jakub HolĂ˝ 2021-07-02T20:50:39.363500Z

@alex.sheluchin doesn't fulcro-exercises fit this?

tony.kay 2021-07-02T22:21:52.366400Z

I found one issue in Inspect that could explain the problems we sometimes have with it: The db tab remembers what watches you've added, and those are written using pr-str to the browser local storage. Unfortunately, pr-str is not symmetric with read-string, and writing a transit type this way (e.g. Fulcro tempid) causes the read-string to throw an exception. I've wrapped the read-string in a try/catch that will clear these (which are probably useless to remember anyway). I have uploaded the fixed Chrome version to the store...should come out within a few weeks. In the meantime, you can always just Inspect the inspector, and clear local storage, or reinstall the plugin.

tony.kay 2021-07-02T22:22:17.367Z

I'll upload the release zipfile to the Releases in the github repo, if you want to manually upgrade. Version 3.0.5

2👍3🎉