omcljs / om

ClojureScript interface to Facebook's React
6.66k stars 363 forks source link

Behaviour of merging data from a remote #829

Closed crazyvan closed 7 years ago

crazyvan commented 7 years ago

With the following initial app state, reconciler and send function:


(def app-state
{:app/message
  {:request "Initial request"
  :response ""}})

(def reconciler
  (om/reconciler
    {:state (atom app-state)
     :parser (c/parser {:read read
                        :mutate mutate})
     :send send-request
     :remotes [:message-remote]}))

(defn send-request [{:keys [message-remote]} cb]
  (cb {:app/message
       {:response "mock response"}}))`

when the remote is invoked the :response key is updated correctly, however, the :request key is
removed from the application state.

Is this intended behavior or is there something else that needs to be done to preserve
keys that have not changed?
livtanong commented 7 years ago

The cb does a simple merge at the top level. In other words, it would be like merging {:app/message 2} into {:app/message 1}.

To preserve the :request key, you should specify your own merge function

(defn merge-fn [reconciler state novelty query]
  ;; Condition for using custom merge.
  ;; Usually you get this information via the query. 
  ;; I unpack query into an ast so I can have more control.
  ;; Generally you want to only use your custom merge when needed in case 
  ;; you have other remotes that only need a simple merge.
  (if (use-custom-merge? (om/query->ast query))
    ;; define the keys in the app state that will be affected
    {:keys [:app/message] 
     ;; where novelty is {:app/message {:response "mock response"}}
     :next (assoc-in state [:app/message :response] 
             (get-in novelty [:app/message :response]))
     :tempids nil}
    (om/default-merge reconciler state novelty query)))

(def reconciler
  (om/reconciler
    {:state (atom app-state)
     :parser (c/parser {:read read
                        :mutate mutate})
     :send send-request
     :merge merge-fn
     :remotes [:message-remote]}))

See

  1. https://github.com/omcljs/om/wiki/Documentation-(om.next)#reconciler
  2. https://github.com/omcljs/om/wiki/Documentation-(om.next)#merge
swannodette commented 7 years ago

Not a bug, closing this one.