Fork me on GitHub

hi - is there anything that can cause queries to the root of the app db to work in one component but not another?


i have two components with queries that look like this: [{[:globals '_] [:selection]} ...], and one receives the contents of the db at path [:globals :selection] whereas the other one receives nil


the signature of the two components is as follows:


(defsc Participant [this {:participant/keys [id full-name telephone] :keys [globals] :as props} {:keys [on-select participant/selected?]}]
  {:query [{[:globals '_] [:selection]}
   :ident [:PARTICIPANT/by-id :participant/id]}


(that one gets nil)


(defsc ParticipantUtilities [this {:keys [globals participant-form ui/form-visible?]}]
  {:query [{[:globals '_] [:selection]}
           {:participant-form (prim/get-query form-participant/ParticipantFormModal)} :ui/form-visible?]
   :ident (fn [] [:participant/utilities :singleton])
   :initial-state {:ui/form-visible? false
                   :participant-form {}}}


that one correctly gets the contents of [:globals :selection]


initial state. The component must be reachable through the graph in order to resolve link queries. In other words make sure you can traverse the graph to the component via the database.


you’ll have to forgive me, i’ve been reading the docs for a while but it’s not sunk in yet. how does initial state affect whether the component is reachable through the graph? i thought it was just a way of setting the state of the component given the params passed to it? and what makes a component reachable or unreachable? is there a way for me to tell by looking at the component? thanks.


Ah, good question. Initial state is just one way to create the graph, so you’re right that it isn’t necessarily the problem. But, the general rule is this: A query is relative to it’s parent. The parent must compose the child into the query, and something (initial state, a mutation, a load, etc.) has to put something in the graph at that path for the query to mean anything in the child.


The link queries make it a little confusing, because they are a “reach back to the root and get some data”, but queries are run as a walk of the reified graph, and if there isn’t a real data path to the component, then its query will never actually be run


So, if you hang some component out in the React tree in code, then that tree is what will render. The query will, however, run only as far as the data is linked together. The most common place where ppl run into this mistake is when they put a child in the tree that has only a link query, and expect it to magically work…but that kind of thing could be nested very deep in some side-branch of a tree that is otherwise “empty”, and it makes no sense to “fill in the gaps” of the data tree for you….what should we hand to all of those “in-between” components in that otherwise empty data graph?


So, the requirement is that you at least put something in place at each (stateful) node…even if it is nothing but an empty map at a leaf or an ident linkage from one component to another


I’m guessing your Participant has no state yet where you’re rendering it.


thanks - i think that makes sense. i’ll read the rest of the code and see if i can work out what’s happening from what you describe


Hey, I saw that Fulcro project itself has migrated to Yarn. Any reason why yarn instead of npm?

Abhinav Sharma12:10:04

Hi @U66G3SGP5, I am guessing that it might be because of the benefits of the reduced number of deps perhaps or it being faster. Coming form the nodejs world, I think this is the general pref as of now - correct me if I’m wrong here.


I haven't worked with nodejs, so I don't know what Yarn offers over NPM for packet management

Abhinav Sharma13:10:18

Oh, I see. So, this might be a good summary Note that npm is changing as well however, yarn definitely does the package installation and management faster ( among other advantages)


just trying it out really…was the recommended approach for native, which I started using earlier this month. Seemed faster. so far so good

Björn Ebbinghaus13:10:31

(defsc Root [this {:keys [field]}]
  {:query [:field]
   :ident (fn [] [:component/id :ROOT])
   :initial-state (fn [_] {:field "Empty"})}
  ; State after initial-state: {:field "Empty"}
  (input {:value field
          :onChange #(m/set-string! this :text-field :event %)}))
  ; state after set-string!: {:field "Empty" :component/id {:ROOT {:field "Not empty"}}}
I have the situation where the initial-state is not normalized. Nevertheless, the input field has the value "Empty". But when I mutate field, the ident is respected and after that "Not empty" is rendered. Any ideas what is going on?

Björn Ebbinghaus13:10:10

Note that If I query for something else then field the component has the right props until the first mutation is done.


you should not use an ident on root…it confuses things @mroerni


root is special (for the moment) and corresponds to the root of the graph, which is the db itself. It can’t both be the root, and be in a table.


I generally recommend making a very simple root that does nothing more than compose in the real app. At some point I’d like to relax this restriction (it isn’t that hard), but I have not gotten to it since it has such an easy workaround

Björn Ebbinghaus15:10:53

Ok. Thought it was something like this. Usually I don't use the root like I would use a normal component. I want to introduce Fulcro to a few local developers and tried to minimize the lines of code I have to show. Btw. the root in the template has an ident.