Skip to content

Step 05: talking to the server

Cole Padden edited this page Jan 23, 2016 · 9 revisions

Browse code - Diff - Live demo

To reset your workspace for this step, run git checkout step-5.

You will probably need to restart you Figwheel process and install the dependencies. Type ^C in your terminal to stop your Figwheel build process, then run :

lein do deps, clean, figwheel

So far we've been cheating by using a hardcoded list of phones, now let's make our application more realistic by loading the list of phones via HTTP.

Our HTTP server serves the list of phones in JSON format at the path /phones/phones.json. What we need to do is:

  1. Send an AJAX HTTP request at GET /phones/phones.json
  2. Parse the JSON response into Clojure data structures so we can manipulate them
  3. When the response arrives, update the state of our application with the list of phones we've just loaded.

As a first change, our atom states now starts with an empty vector of phones :

(defonce state
  (rg/atom {:phones []
            :search ""
            :order-prop :name
            }))

Reagent does not provide any way of dealing with AJAX (which is a good thing, a view library should not be concerned with this), so we'll use another ClojureScript library, called cljs-ajax. Let's import this library and require it in our namespace:

project.clj:

:dependencies [;; ...
                 [cljs-ajax "0.3.14"] 
                 ]

core.cljs:

(ns reagent-phonecat.core
    (:require ;; ...
              [ajax.core :as ajx])
    )

We'll write a single load-phones! function to fetch the phones and put it in our app state:

(defn load-phones! "Fetches the list of phones from the server and updates the state atom with it" 
  [state]
  (ajx/GET "/phones/phones.json"
           {:handler (fn [phones] (swap! state assoc :phones phones))
            :error-handler (fn [details] (.warn js/console (str "Failed to refresh phones from server: " details)))
            :response-format :json, :keywords? true}))

Let's deconstruct this:

  • we pass our state atom as a parameter to our function
  • :handler (fn [phones] (swap! state assoc :phones phones)) is the callback that actually updates our state
  • :response-format :json, :keywords? true means "the response will be in JSON, and I want the keys in maps to be keywords (not strings)"
  • :error-handler is the callback that's called when something goes wrong, in this case we'll just log the error and do nothing about it

Finally, we call our function when we initialize our app:

(defn init! []
  (load-phones! state)
  (mount-root))

Summary

We've learned how to use the cljs-ajax library to make AJAX more practical from ClojureScript.

Next Step.