Once you’ve grokked the Re-Frame philosophy for building truly reactive applications on React in ClojureScript, you will want to apply it everywhere. One obvious and ubiquitous application of effects is asynchronous HTTP requests, and of course there is an officially sanctioned library for handling these. One problem: it relies on an AJAX library that only works with the browser XHR implementation. So what can we do in React Native-based Clojurescript apps?

It’s actually very simple, and can be accomplished in about ten lines of code. We’ll rely on cljs-http, a core.async-based HTTP library.

(ns my-app.events
  (:require [cljs-http.client :as http]
            [cljs.core.async :refer [go <!]]
            [re-frame-core :refer [reg-fx dispatch]]))

(reg-fx
 :http
 (fn [{:keys [url method opts on-success on-failure]}]
   (go
     (let [http-fn (case method
                     :post http/post :get http/get
                     :put http/put :delete http/delete)
           res     (<! (http-fn url opts))
           {:keys [status success body]} res]
       (if success
         (dispatch (conj on-success body))
         (dispatch (conj on-failure body)))))))

The opts param here is a map that will handle everything that cljs-http takes as input, like :headers, or :multipart-params. That documentation can be found in the cljs-http README.

Here’s an example of how you might use it:

(reg-event-fx
  :update-password
  (fn [_ [_ email old-pass new-pass]]
    {:http {:method :post
            :url "https://my-service.example.com/update-password"
            :opts {:edn-params {:user/email email
                                :user/old-password old-pass
                                :user/new-password new-pass}}
            :on-success [:save-user]
            :on-failure [:alert-failure]}}))

You’ll want to have registered the :save-user and :alert-failure events before using them, of course.

Hopefully this small event function has been helpful. It’s short enough that I don’t think it rises to the level of being a library instead of a blog post, and in fact I think most people will want to customize which keys they want to handle. I personally have replaced opts with just edn-params and headers as those are all I use. Feel free to reach out over twitter or in #cljsrn on Clojurians Slack with questions.