Fork me on GitHub

I have some data that I’ve fetched from the server, but it’s not in the format that I want to store it in the global atom. How would I go about modifying the response and storing it in the correct location in the atom? I’ve been considering adding a :merge option to my reconciler configuration. At this point, I’m reading the source code to figure out how this works and I’m at a loss for what to put in :tempids.


@daniel.dyba welcome! om next is really great. i recommend asking your question in the #om channel or even in the #clojurescript channel. I have code that figures out where things live in the clientside/js/browser atom and slides them on in. let me see if I can find an example for you my good man.


@sova thanks! do the #om and #clojurescript channels have more activity?


I figured I’d choose this channel because it’s om-next specific


#om has more activity this #om-next channel is not really where discussions go down (david nolen creator of om and and antonio [co-maintainer] spend their time in #om


ah, thanks for the tip! @sova


So I had to ask for help writing a merge function for the local atom...


@joshjones hooked me up with a great chunk of code 😃


I'll paste you what I have, it has been catered to my specific situation


the last time I tried writing a custom merge function, I found myself in an infinite loop 😕


it kept re-rendering the components


So you can click to expand that snippet.


Hmm this is more for updating an existing (nested) set of atom values [some of my items have "ratings" and there's one "active blurb" that has its own ID.


@sova which one is the custom merge function? Neither seems to have the correct number of arguments


Anyway, I don't want to confuse you, there are experts that can help in #om for sure, but you can see that this snippet uses merge. you may have to use merge-with sometimes as to not overwrite the existing atom with just 1 entry


Okay well, tell me more about your data


So you get some entries from the server, you want to insert them into the atom in the right place, yar?


well this function actually uses assoc


and a lot of my functions to add into the atom use assoc-in


Line 2355 pulls the custom merge function I specify when I create my reconciler and then my custom merge gets called on Line 2356


It requires that I return a map with :keys, :next, and :tempids. I know what to put in :keys and :next but not :tempids


Ah you are updating the whole atom with a delta and a merge function to handle it. Cool. Mmm, you need to have tempids... I'm gonna say: ask in the #om channel, I think there is a placeholder function but i'm not sure. Your database could push tempids across the wire with the data update, but again someone more experienced in #om will be able to set you straight faster


@daniel.dyba for all my inserts into the atom I use a specific mutate function for each attribute branch in the atom.... Have you tried just using an underscore for tempids ?


@sova I thought underscores only work when you’re destructuring. Are you suggesting using an underscore as a return value?


destructuring yes, not as a return.


@sova I copied my question to the #om channel too


@sova Right, but Line 2356 expects a return value for :tempids


oh good. yeah they might take a little while but the experts live there. hmm so can you show me the way you're invoking this, maybe I can help more


you can’t use destructuring at this point


So you have a remote specified, and therefore it is trying to get your tempids


;; where on is a reference to
  (def reconciler (on/reconciler
                   {:state m/init-data
                    :parser parser
                    :send (m/send-to-chan send-chan)
                                        ; FIXME: We're missing a merge function that does a custom merge on the data
                                        ; we get back from the server
                    :merge (fn [reconciler state delta query]
                             {:keys []
                              :next state
                              :query nil})
                    ; it should return a map with the keys: :keys, :next, :tempids
                    ; what's the purpose of tempids???
                    :remotes [:list-models]}))


there’s more code to this obviously, but this is the heart of the matter


i think you can just generate some tempids for this specific task, they don't need to be anything special .. i think the way this is normally done is with [in your case] on/tempid


because it needs a fake index as it's moving them from the database into the atom, is my understanding.


Right, but do I generate one? Do I generate the number equivalent to the count of the list I get back from the server? And what data structure is tempids?


Suppose the response from the server is:

  "model": {
    "items": [


Then that response is captured here:

(defn model-list-loop
  (go-loop [cb (<! c)]
    (let [results (<! (reg/list-models))]
      (cb {:list/model-names (get-in results [:model :items])}))
    (recur (<! c))))


Where results is the map that represents the above server response


and you're looping over all your remotes there?


model-list-loop is called immediately after the reconciler is defined

sova-soars-the-sora17:11:52 has an internal representation for stuff in the atom, which is where I think tempids come in.


For every new transaction you need to have a tempid, but I don't know to be honest, i never used merge to update to the atom. except for those snippets i showed you. I think just one tempid per transaction (like the ones you see in the javascript console) is sufficient


you've probably seen this video but at around 19:43 he goes into tempids


anyway, good luck dude, sorry i couldn't be more help 🙂


@sova thank you for taking the time to answer my questions!