Say I have a component which needs to request some data from server before rendering.
What I have now is something like with cljs-ajax
library:
(def data (r/atom nil))
(defn component [id]
(r/create-class {:reagent-render simple-div
:component-did-mount (partial get-data id)}))
(defn get-data [id]
(GET (str "/api/" id)
{:handler init}))
(defn init [response]
(let [data1 (:body response)
data2 (compute data1)
data3 (compute2 data2)]
(reset! data (compute3 data1))
(.setup @data data1)
(.setup2 @data data2)
(.setup3 @data data3))
the setup
functions are some foreign JS library functions with side effects.
This works but I don't feel like this is the correct way to do callback.
Not to mention if I need to GET
other datas based on the first data I got, and then other datas based on that, it would be a very nasty chain of callbacks.
Is there a better, clean way of doing this kind of ajax request in reagent/clojurescript?
The local binding with let sets up a Reagent atom that will hold our local state. In Clojurescript, data structures are immutable per default. But we need our quotes to change when the user clicks a button, so we use the Reagent implementation of atom. An atom is like a container that holds a mutable value.
simple Ajax client for ClojureScript and Clojure. cljs-ajax exposes the same interface (where useful) in both Clojure and ClojureScript. On ClojureScript it operates as a wrapper around goog.net.XhrIo or js/XmlHttpRequest, while on the JVM it's a wrapper around the Apache HttpAsyncClient library.
In Clojurescript, data structures are immutable per default. But we need our quotes to change when the user clicks a button, so we use the Reagent implementation of atom. An atom is like a container that holds a mutable value. When you want to take a peek into it, you have to de-reference it with @.
We have seen that React is a good platform for writing ClojureScript applications, but we have not yet written any code.
The most common way to make requests is cljs-http. Add [cljs-http "0.1.39"]
to the dependencies in project.clj
and restart the figwheel process in the terminal to pick up the new dependency.
(ns my.app
(:require
[cljs.core.async :refer [<!]] [cljs-http.client :as http])
(:require-macros [cljs.core.async.macros :refer [go]])
(go (let [response (<! (http/get "data.edn"))]
(prn (:status response))
(prn (:body response))))
Cljs-http is a nice way to manage HTTP requests. It uses core.async channels to deliver its results. For now, all you need to focus on is that http/get and http/post calls should occur inside a go form, and the result is a channel that can have its result read with
Dependent http gets can be chained together in a sensible way in a single go block that looks like sequential code, but occurs asynchronously.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With