can I fetch the remote data myself in om? I didn't quite understand how the sync works in om, so I'm thinking to just go with what I know and implement the fetching of data from the servers as mutation functions
(my server also doesn't accept the pull syntax, which I suspect is necessary if I let om to do the sync for me)
@snichme I found the problem, 🤕 , initial rendering is not happening if the data is not present (changing the initial value of the counter to 100 did the trick)
ahh, there was no data in the state?
Seems correct, since, why render if the data isn’t there?
🙂 well one could expect to at least make the initial rendering, and let the component decide what to display when no data is there
but it can be done with non-nil empty values like {}
[]
or ""
What do you mean with om syncing?
By default there isn’t any syncing, you return a {:remote true} from a mutation which tells it to run on the server. But you can switch it to go regular REST
for example one remote per endpoint
does a component need to include the query of all its children in its own query? because I see that data for a component arrives through props, so it looks to me like a component is responsible to pass the correct data to its children
Yes, parent query children for what data it needs, and should then pass that data to the child in the render method
Hi everyone, I realized the problem I’m having with Om Next is that the value of (om/props this)
changes three times during the course of two API calls to a server.
The first call to the render
method inside my component yields props:
clojure
{:selection/models
{:id "_model-names",
:selected nil,
:label "Select a Model from Registry:",
:key-fn :value,
:label-fn :text,
:options []},
:selection/model-versions
{:id "_model-versions",
:selected nil,
:label "Select a Model Version from Registry:",
:key-fn :value,
:label-fn :text,
:options []}}
The second call to render
yields:
{:selection/models
{:id "_model-names",
:selected nil,
:label "Select a Model from Registry:",
:key-fn :value,
:label-fn :text,
:options
[{:value "FHA", :text "FHA"}
{:value "USDA", :text "USDA"}
{:value "VA", :text "VA"}]}}
The third call to render
yields:
{:selection/model-versions
{:id "_model-versions",
:selected nil,
:label "Select a Model Version from Registry:",
:key-fn :value,
:label-fn :text,
:options
[{:value "_SNAPSHOT_", :text "_SNAPSHOT_"}
{:value "v0_1_0", :text "v0_1_0"}
{:value "v0_1_1", :text "v0_1_1"}
{:value "v0_1_2", :text "v0_1_2"}
...]}}
But if you note, the second call drops the top-level keyword :selection/model-versions
The third call drops the top-level keyword :selection/models
And I suspect this is happening here in my app-loop
:
(defn app-loop
[c]
(go-loop [[{:keys [op] :as m} cb] (<! c)]
(when (= op :list-model-versions)
(let [results (<! (reg/list-model-versions "FHA"))
{model-versions-selection :selection/model-versions} (update-in init-data
[:selection/model-versions :options]
(fn options-collector [opts coll]
(apply conj opts coll))
(mapv (fn optionify [s]
{:value s :text s})
(get-in results [:model :items])))]
(println "list-model-versions in app-loop")
(cljs.pprint/pprint model-versions-selection)
(cb {:selection/model-versions model-versions-selection})))
(when (= op :list-models)
(let [results (<! (reg/list-models))
{model-selection :selection/models} (update-in init-data
[:selection/models :options]
(fn options-collector [opts coll]
(apply conj opts coll))
(mapv (fn optionify [s]
{:value s :text s})
(get-in results [:model :items])))]
(println "list-models in app-loop")
(cljs.pprint/pprint model-selection)
(cb {:selection/models model-selection})))
(recur (<! c))))
I have two callbacks, but each one updates only part of the initial data with the response I get from the API
This leads me to wonder if I should be retrieving the state of the app from the reconciler and update that instead of init-data
Any help would be much appreciated! 🙂
I’ve shrunk my app-loop
to this:
(defn app-loop
[c]
(go-loop [[{:keys [op] :as m} cb] (<! c)]
(println "inside app-loop")
(cljs.pprint/pprint m)
(when (= op :list-model-versions)
(let [results (<! (reg/list-model-versions "FHA"))]
(cb (mapv (fn optionify [s]
{:value s :text s})
(get-in results [:model :items]))
{:selection/model-versions [:options]})))
(when (= op :list-models)
(let [results (<! (reg/list-models))]
(cb (mapv (fn optionify [s]
{:value s :text s})
(get-in results [:model :items]))
{:selection/models [:options]})))
(recur (<! c))))
and plan to use a custom merge
function in my reconciler to merge the correct state. I have a hunch this might be in line with the way Om Next is architected.I’m taking advantage of the second parameter in the callback to pass along the query where the novelty must be introduced
Well, I finally got this to work and removed the flicker effect I mentioned earlier. The custom merge
function did the trick:
:merge (fn [reconciler state novelty query]
(cond
(contains? query :selection/models)
{:keys (conj (get state :selection/models) :options)
:next (update-in state
(conj (get state :selection/models) :options)
(fn options-collector [opts coll]
(apply conj opts coll))
novelty)}
(contains? query :selection/model-versions)
{:keys (conj (get state :selection/model-versions) :options)
:next (update-in state
(conj (get state :selection/model-versions) :options)
(fn options-collector [opts coll]
(apply conj opts coll))
novelty)}
:else
{:keys []
:next state
:query nil}))
I have to say, while Om Next is better than Om Now, the uphill climb to learn Om Next is VERY steep
Please chime in if you think my implementation goes against how Om Next is intended to be used