-
-
Notifications
You must be signed in to change notification settings - Fork 715
Talking To Servers
This page describes a pattern which re-frame apps can use when "talking" to backend services.
For explanation purposes, let's assume there's a server endpoint at the URL "http://json.my-endpoint.com/blah" which will return json. Our job is to GET json from that endpoint and put a processed version of it into app-db
.
Some user initiated event will often trigger the process. Let's imagine the trigger is simply a button click:
(defn request-it-button
[]
[:div {:class "button-class"
:on-click #(dispatch [:request-it])} ;; get data from the server !!
"I want it, now!"])
Notice the on-click
handler - it does a dispatch
to kickstart the process.
That :request-it
event will need a handler. When we write it, let's use cljs-ajax as the HTTP workhorse.
We want the handler to:
- Initiate the HTTP GET
- Update some flag in
app-db
which will trigger a modal "Loading ..." message to show in the UI.
(ns my.app.handlers
(:require [ajax.core :refer [GET POST]]
[re-frame.core :refer [register-pure-handler]))
(register-pure-handler
:request-it ;; <-- the button dispatched this id
(fn
[db _]
;; kick off the GET, making sure to supply a callback for success and failure
(ajax.core/GET
"http://json.my-endpoint.com/blah"
{:handler #(dispatch [:process-response %1]) ;; further dispatch !!
:error-handler #(dispatch [:bad-response %1])}) ;; further dispatch !!
;; update a flag in `app-db` ... presumably to trigger UI changes
(assoc db :loading? true))) ;; pure handlers must return a db
Notice that the GET callbacks issue a further dispatch
.
Such callbacks should not attempt to close over db
themselves, or make any changes to it, because, by the time these callbacks happen, the value in app-db
may have changed. Whereas, if they dispatch
, then the event handlers looking after their dispatch will be given the latest copy of the db.
The GET success handler:
(register-pure-handler ;; when the GET succeeds
:process-response ;; the GET callback dispatched this event
(fn
[db [_ response]] ;; extract the response from the dispatch event vector
(-> db
(assoc :loading? false) ;; take away that modal
(assoc :data (js->cljs response)))) ;; fairly lame processing
A normal handler would have more complex processing of the response. But we're just sketching here, so we've left is easy.
There'd also need to be a handler for the GET :bad-response
too. Left as an exercise.
Deprecated Tutorials:
Reagent: