Fork me on GitHub

I have a generic dropdown component with an ident that can be pointed at different tables depending on its props. When it is first mounted in the UI, there is nothing in the DB where its ident is pointing, so in its :componentDidMount it runs a load that populates the DB and creates a derived list of options for the dropdown list. However, even though the DB updates fine, the component never sees the new props and never renders again. I’m guessing this is because when it was first mounted, there was nothing in the DB where its ident pointed. Does this mean its parent component needs to populate the DB before mounting it? Is there any way the component can take care of this itself?


I suggest you check pre-merge, this feature is my go-to to handle state initialization:


hmm, :pre-merge isn’t called. it seems like all of the examples in the book have some external component only loading the comp after it exists in state


oh, I wasn’t passing through the props correctly. Or rather, because I’ve made this component a global-like thing, the only props it gets from its UI parent is the key it needs to find itself in global app-state, and the currently selected value for the dropdown select. The list of options it loads directly from global app-state, which is the part I wasn’t realizing. So in other words I have something like this working now:

:componentDidMount (fn [this]
                        (let [props       (comp/props this)
                              ident       (comp/ident this props)
                              app-state   (fapp/current-state SPA)
                              ref-props   (get-in app-state ident)]
                          (when (empty? (:ui/options ref-props)) ; load stuff into :ui/options ...
Also its parent needed to watch the root state key that it loads into in order to rerender it when its data gets added:
(defsc Parent [_ _]
{:query [[:root.lookup.options/ns '_]]} ...)
The nice thing about this is I use this lookup dropdown all over the place to select a joined entity when editing an entity, or in dynamically-added list filters to select which referenced entity to filter a list by, etc. Now the parent component has only its local state to worry about rather than having to thread through a bunch of lists of options to every dropdown ... it doesn’t even need to worry about whether the data exists or not, the dropdown will initialize itself, show its own loading status, and show itself when it’s ready.


thanks for the help anyway. pre-merge looks interesting, I just haven’t needed to use it yet i suppose

Chris O’Donnell12:01:41

I'm using the dynamic router, and I find that when I first call dr/change-route after page load to a route with dr/route-deferred in its :will-enter that the first route in the router targets flashes before the router goes into a pending state. This isn't the end of the world; I've worked around it by making the first component a special Loading component that matches the pending state. Have other people done differently? Is this intended behavior?

Chris O’Donnell13:01:34

On a related note, is it possible to define a "not found" handler in a dynamic router? For context, I'm using html5 routing, and I need to figure out how to handle it when a user loads a url that doesn't correspond to any of my routing targets.


Hi, I have a (df/load ....) in a mutation and that works fine, I also have a (uism/load .... ) with the same parameters in my statemachine handler, but for some reason that doesn't seem to work, I cannot see any network activity as a result (I do see however my logs statements in the same handler, so it does get called)


Any ideas what I could be doing wrong?


@slawek098 I have started using Fulcro about 2 months ago and I have found it a quite a learning curve and I have yet to really get comfortable with it. That said it does seem to include everything including the kitchen sink.


@thomas I haven't even entered the kitchen.


@codonnell so, it is hard to know where the responsibility of a library should end. I consider D.R. to be “pretty close” to done, and have been considering the “valid routes” question to be an application concern when you’re translating the URL string into a vector route. But, now that you mention it, it would be handy to just be able to ask if a path is “route-able”.

Chris O’Donnell00:01:13

@tony.kay That would certainly be useful from my perspective. I'm happy to work with you to get a PR together if you're interested.


Sure. There is already code that tries to match a route…I may have already even written a helper that would suffice…the route-target function is probably pretty close


but might be nice to have more descriptive failure modes


@thosmos hard to say. load is pretty straightforward. you sure you threaded env to the output of the handler???


load does not side-effect


it generates a new env that will trigger the load when returned


you’re probably doing this:

(uism/load env ...)
(-> env ...)

;; instead of
(-> env
  (uism/load ...)


I believe that reply was for @thomas


ah, sorry… 🙂




no problem


I'm not sure if even my problem is correct.. have a look if you can: . Basically I am trying to build component which will be more or less accepting list of idents... I'm new to Fulcro, not sure how to explain it directly. I only expect to have one instance of this component, I'd like to fetch all wires defined (that works) and display list of those. I know how to do this when I have one list with ident, but not sure how to skip ident for list while still keeping Root and WireList separate. That's my db:


Your WiresList expects a props map with a key :wires but Root is handing it a vector? So in Root try:

(ui-wire-list {:wires wires})


Oh, it's working now. Thank you!

👍 4

If you wanted multiple lists of wires in Root, then it would make sense to use an ident in WireList and call (get-query WireList) from Root


Do you use Fulcro Inspect to view what’s in the DB?


Also I find it helps to sometimes put debug statements that just print out everything in props. Then you’d see that WireList was receiving a vector instead of the expected map


Hah, I had print printing wires in WireList.


But it returned nil


This works, but you’re not really using the :query in WireList. It could even just be a function. To reuse it both for all wires and multiple lists of fewer wires would mean using the ident and using a special ident value like :all-wires for your big list.


Ah yes {:keys [wires] :as props}


I’m doing something similar, I have a generic list component that I move around to a bunch of different tables by changing its ident value.


Thank you very much for help!


Is this somehow fundamentally wrong?


@slawek098 why do you want to skip ident for list? and keep it separate (what do you mean) from root?


if you know you will only have one list of a component in the db, you could give it the same ident (fn [] [:table/by-id :SINGLETON]) instead of :entity/id


I'd like to create WireList component, which will have only one instance and display all wires from :wires list.


If you want things normalized there is no level to skip. If you will never ever show a wire in a different component, and don’t care about losing normalization as a result, then drop the subquery component and just do [{:wire-list/wires [:wire/id]}] and whatever else you want from each wire…then just render the list locally


you can always manually generate a subquery (or just use a prop that gets an opaque bag of data from the server…assuming you write your server to deliver it). Subqueries with components are about sanity of data (normalization)…you can always choose to skip that.


After following tutorial in Fulcro Book I had WireList component which took [:wire-list/id {:wire-list/wires (comp/get-query Wire)}]


But as I just want to list all wires which are here, I wanted to skip this level.


@tony.kay We decided to switch from Datomic on-prem to Cloud (long story), and what I am running into is that Datomic Cloud is stuck on a much older version of Transit, which doesn’t have the write-meta function. On the server, we only use a small part of Fulcro (api handler and config component), so I could pull that out and rewrite it to not use metadata on the wire. But I would like to know what the consequences of that would be, i.e. what are you using the metadata for?


@mdhaney The primary purpose of the metadata stuff is for SSR


the Fulcro dynamic queries use metadata on the items in state to track what components go with the query elements…so, if you generate that on a server and serialize it with transit then SSR won’t restore it (and then won’t work right)


so, if you’re not doing server-side rendering, it makes no difference at all


(at least as far as I remember)


Perfect, thanks! Do you think it would be worthwhile for me to separate this out to a separate project, for other people to use? Something with just the minimal Fulcro server bits that people could use for Datomic Cloud projects. Probably the biggest concern would be keeping it in sync with Fulcro, although it seems like the server bits won’t be changing as much since we started relying on Pathom.


If you can see a way to make it part of Fulcro proper that’s fine as well…


I know the deps stuff gets hard to deal with


I.e. is there a way to get it to compile “either way”?


That would be awesome. I mentioned a separate lib because I also had add a lot of exclusions to the Fulcro import in deps to get this far, but that could be handled with documentation. Let me get it working first, then I’ll see if there’s an easy way to integrate it with the main Fulcro lib.