{"id":13788493,"url":"https://github.com/Day8/re-frame-http-fx","last_synced_at":"2025-05-12T02:33:23.733Z","repository":{"id":9802891,"uuid":"63392065","full_name":"day8/re-frame-http-fx","owner":"day8","description":"A re-frame \"effects handler\" for performing Ajax tasks (via cljs-ajax)","archived":false,"fork":false,"pushed_at":"2022-01-10T12:17:40.000Z","size":257,"stargazers_count":260,"open_issues_count":8,"forks_count":25,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-05-05T00:02:33.201Z","etag":null,"topics":["re-frame"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/day8.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"mike-thompson-day8"}},"created_at":"2016-07-15T04:38:04.000Z","updated_at":"2025-04-27T03:04:33.000Z","dependencies_parsed_at":"2022-08-07T05:01:20.360Z","dependency_job_id":null,"html_url":"https://github.com/day8/re-frame-http-fx","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/day8%2Fre-frame-http-fx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/day8%2Fre-frame-http-fx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/day8%2Fre-frame-http-fx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/day8%2Fre-frame-http-fx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/day8","download_url":"https://codeload.github.com/day8/re-frame-http-fx/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253662802,"owners_count":21944134,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["re-frame"],"created_at":"2024-08-03T21:00:47.991Z","updated_at":"2025-05-12T02:33:23.450Z","avatar_url":"https://github.com/day8.png","language":"Clojure","funding_links":["https://github.com/sponsors/mike-thompson-day8"],"categories":["front-end","Tools"],"sub_categories":["Effect Handlers"],"readme":"\u003c!-- [![CI](https://github.com/day8/re-frame-http-fx/workflows/ci/badge.svg)](https://github.com/day8/re-frame-http-fx/actions?workflow=ci)\n[![CD](https://github.com/day8/re-frame-http-fx/workflows/cd/badge.svg)](https://github.com/day8/re-frame-http-fx/actions?workflow=cd)\n[![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/day8/re-frame-http-fx?style=flat)](https://github.com/day8/re-frame-http-fx/tags) \n[![GitHub pull requests](https://img.shields.io/github/issues-pr/day8/re-frame-http-fx?style=for-the-badge\u0026logo=github)](https://github.com/day8/re-frame-http-fx/pulls)\n--\u003e\n[![Clojars Project](https://img.shields.io/clojars/v/day8.re-frame/http-fx?style=for-the-badge\u0026logo=clojure\u0026logoColor=fff)](https://clojars.org/day8.re-frame/http-fx)\n[![GitHub issues](https://img.shields.io/github/issues-raw/day8/re-frame-http-fx?style=for-the-badge\u0026logo=github)](https://github.com/day8/re-frame-http-fx/issues)\n[![License](https://img.shields.io/github/license/day8/re-frame-http-fx?style=for-the-badge)](LICENSE)\n\n## HTTP Effects Handler For re-frame\n\nThis re-frame library contains an HTTP [Effect Handler](https://github.com/day8/re-frame/blob/master/docs/Effects.md).\n\nKeyed `:http-xhrio`, it wraps the goog xhrio API of [cljs-ajax](https://github.com/JulianBirch/cljs-ajax).\n\n\u003e **IMPORTANT**: This effect handler depends entirely on the API of [cljs-ajax](https://github.com/JulianBirch/cljs-ajax). Make sure you are familiar with the API for cljs-ajax, and especially with [`ajax-request`](https://github.com/JulianBirch/cljs-ajax#ajax-request) before proceeding.\n\n## Quick Start Guide\n\n### Step 1. Add Dependency\n\nAdd the following project dependency: \u003cbr\u003e\n[![clojars](https://img.shields.io/clojars/v/day8.re-frame/http-fx?style=for-the-badge\u0026logo=clojure\u0026logoColor=fff)](https://clojars.org/day8.re-frame/http-fx)\n\nRequires re-frame \u003e= 0.8.0\n\n### Step 2. Registration And Use\n\nIn the namespace where you register your event handlers, perhaps called `events.cljs`, you have 2 things to do.\n\n**First**, add this \"require\" to the `ns`:\n```clj\n(ns app.core\n  (:require\n    ...\n    [day8.re-frame.http-fx]   ;; \u003c-- add this\n    ...))\n```\n\nBecause we never subsequently use this `require`, it\nappears redundant.  But its existence will cause the `:http-xhrio` effect\nhandler to self-register with re-frame, which is important\nto everything that follows.\n\n**Second**, write a an event handler which uses this effect:\n```clj\n(ns app.events              ;; or where ever you define your event handlers\n  (:require\n    ...\n    [ajax.core :as ajax]    ;; so you can use this in the response-format below\n    ...))\n    \n(reg-event-fx                             ;; note the trailing -fx\n  :handler-with-http                      ;; usage:  (dispatch [:handler-with-http])\n  (fn [{:keys [db]} _]                    ;; the first param will be \"world\"\n    {:db   (assoc db :show-twirly true)   ;; causes the twirly-waiting-dialog to show??\n     :http-xhrio {:method          :get\n                  :uri             \"https://api.github.com/orgs/day8\"\n                  :timeout         8000                                           ;; optional see API docs\n                  :response-format (ajax/json-response-format {:keywords? true})  ;; IMPORTANT!: You must provide this.\n                  :on-success      [:good-http-result]\n                  :on-failure      [:bad-http-result]}}))\n```\n\nLook at the `:http-xhrio` line above. This library defines the \"effects handler\"\nwhich implements `:http-xhrio`.\n\nThe supplied value should be an options map as defined by the simple interface `ajax-request` [see: api docs](https://github.com/JulianBirch/cljs-ajax#ajax-request). Except for `:on-success` and `:on-failure`. All options supported by `ajax-request`\nshould be supported by this library, as it is a thin wrapper over `ajax-request`.\n\nHere is an example of a POST request. Note that `:format` also needs to be specified (unless you pass `:body` in the \nmap).\n\n```cljs\n(re-frame/reg-event-fx\n  ::http-post\n  (fn [_world [_ val]]\n    {:http-xhrio {:method          :post\n                  :uri             \"https://httpbin.org/post\"\n                  :params          data\n                  :timeout         5000\n                  :format          (ajax/json-request-format)\n                  :response-format (ajax/json-response-format {:keywords? true})\n                  :on-success      [::success-post-result]\n                  :on-failure      [::failure-post-result]}}))\n```\n\n**N.B.**: `ajax-request` is harder to use than the `GET` and `POST` functions\n cljs-ajax provides, but this gives you smaller code sizes from dead code elimination.\n **In particular, you MUST provide a `:response-format`, it is not inferred for you.**\n\nDon't provide:\n\n     :api     - the effects handler explicitly uses xhrio so it will be ignored.\n     :handler - we substitute this with one that dispatches `:on-success` or `:on-failure` events.\n\nYou can also pass a list or vector of these options maps where multiple HTTPs are required.\n\nTo make **multiple requests**, supply a vector of options maps:\n```\n{:http-xhrio [ {...}\n               {...}]}\n```\n\n### Step 3a. Handling `:on-success`\n\nProvide normal re-frame handlers for `:on-success` and `:on-failure`. Your event\nhandlers will get the result as the last argument of their event vector. Here is an\nexample written as another effect handler to put the result into db.\n\n```clojure\n(reg-event-db\n  ::success-http-result\n  (fn [db [_ result]]\n    (assoc db :success-http-result result)))\n```\n\n\n### Step 3b. Handling `:on-failure`\n\nThe `result` supplied to your `:on-failure` handler will be a map containing various xhrio details (details below). \nSee the fn [ajax-xhrio-handler](/src/day8/re_frame/http_fx.cljs#L23) for details\n\n#### Step 3.1 :on-failure result\n\nA simple failure handler could be written this way ...\n\n```clojure\n(reg-event-db\n  ::failure-http-result\n  (fn [db [_ result]]\n    ;; result is a map containing details of the failure\n    (assoc db :failure-http-result result)))\n```\n\n##### status of 40x/50x\n\nIf the network connection to the server is successful, but the server returns an\nerror (40x/50x) HTTP status code `result` will be a map like:\n\n```clojure\n{:uri \"/error\"\n :last-method \"GET\"\n :last-error \"Service Unavailable [503]\"\n :last-error-code 6\n :debug-message \"Http response at 400 or 500 level\"\n :status 503\n :status-text \"Service Unavailable\"\n :failure :error\n :response nil}\n```\n\n##### Status 0\n\nIn some cases, if the network connection itself is unsuccessful, it is possible\nto get a status code of `0`. For example:\n\n- cross-site scripting whereby access is denied; or\n- requesting a URI that is unreachable (typo, DNS issues, invalid hostname etc); or\n- request is interrupted after being sent (browser refresh or navigates away from the page); or\n- request is otherwise intercepted (check your ad blocker).\n\nIn this case, `result` will be something like:\n\n```clojure\n{:uri \"http://i-do-not-exist/error\"\n :last-method \"GET\"\n :last-error \" [0]\"\n :last-error-code 6\n :debug-message \"Http response at 400 or 500 level\"\n :status 0\n :status-text \"Request failed.\"\n :failure :failed}\n```\n\n##### Status -1\n\nIf the time for the sever to respond exceeds `:timeout` `result` will be a map something \nlike:\n\n```clojure\n{:uri \"/timeout\"\n :last-method \"GET\"\n :last-error \"Timed out after 1ms, aborting\"\n :last-error-code 8\n :debug-message \"Request timed out\"\n :status -1\n :status-text \"Request timed out.\"\n :failure :timeout}\n```\n\n### Optional: Handler for :on-request\n\nIf you need access to the raw request, to for example, cancel long running requests or repeated debounced requests,\nyou can pass an `:on-request` handler that will be called with the request.\n\n```clojure\n(re-frame/reg-event-fx\n  ::http-post\n  (fn [_world [_ val]]\n    {:http-xhrio {:method          :get\n                  :uri             \"https://httpbin.org/delay/60\"\n                  :format          (ajax/json-request-format)\n                  :response-format (ajax/json-response-format {:keywords? true})\n                  :on-request      [::track-slow-request \"my-request\"]\n                  :on-success      [::success-get-result]\n                  :on-failure      [::failure-get-result]}}))\n\n(reg-event-db\n  ::track-slow-request\n  (fn [db [_ my-id xhrio]]\n    (assoc-in db [:requests my-id] xhrio)))\n```\n\nLater if you need to, you could retrieve the request from the app-db and cancel it.\n\n**N.B.**: To prevent memory leaks you need to cleanup the request in both your `:on-success` and `:on-failure` handlers.\nOtherwise the requests will just hang around in your app-db indefinitely.\n \n\n### Tip\n\nIf you need additional arguments or identifying tokens in your handler, then\ninclude them in your `:on-success` and `:on-failure` event vector in Step 3. \n\nFor example ... \n\n```cljs\n(re-frame/reg-event-fx\n  ::http-post\n  (fn [_ [_ val]]\n    {:http-xhrio {:method          :post\n                  ...\n                  :on-success      [::success-post-result 42 \"other\"]\n                  :on-failure      [::failure-post-result :something :else]}}))\n```\n\nNotice the way that additional values are encoded into the success and failure event vectors. \n\nThese event vectors will be dispatched (`result` is `conj`-ed to the end) making all encoded values AND the `result` available to the handlers. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDay8%2Fre-frame-http-fx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDay8%2Fre-frame-http-fx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDay8%2Fre-frame-http-fx/lists"}