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.
Take a look in RAD form.cljc:127, ref-container-renderer
and its usage in the SUI plugin form.cljc line 212
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
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.
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.
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) [])
...
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
arguments are: tree query, id of thing to load. Output is the props of the loaded thing.
use-memo is just so it doesn't keep generating new anonymous components on every render
@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 ❤️
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.
I'll upload the release zipfile to the Releases in the github repo, if you want to manually upgrade. Version 3.0.5