- Greenfield Erlang project to excercise some of the basics
- Haven't done frontend development in years
- Didn't know a thing about React (and still don't know much)
- Biased towards weird and cool techs


(-> react.js reagent re-frame)
- react: A declarative, efficient, and flexible JavaScript library
for building user interfaces.
- reagent: A minimalistic ClojureScript interface to React.js.
- re-frame: A pattern for writing SPAs in ClojureScript, using Reagent.
- Similar architecture to Redux, Om Next and Elm.
- Just functions that produce HTML (hiccup)
- Should be ketp as dumb as possible: re-frame provides other
components to handle reading/writing state.
(defn footer-view
[]
[:footer.footer
[:div.container
[:div.content.has-text-centered
[:p [:strong "HolidayPing"] " by "
[:a {:href "https://github.com/lambdaclass/" :target "_blank"} "LambdaClass"] "."]
[:p [:a.icon {:href "https://github.com/lambdaclass/holiday_ping"}
[:i.fa.fa-github]]]]]])
- Reagent provides
reagent/atom
to manage state: like
clojure.core/atom
, but it keeps track of every time it is deref’ed
- Any component that uses an atom is automagically re-rendered when its value changes.
- re-frame puts all your application state into single
reagent/atom
,
which is called app-db.
- Events allow to write to the db and handle other effectful
interactions (i.e. talk to a server)
- Events are pure functions: they take effects as inputs and return
new effects as data.
(re-frame/reg-event-fx
:auth-submit
(fn [_ [_ {:keys [email password]}]]
{:http-xhrio {:method :get
:uri "/api/auth/token"
:timeout 8000
:headers {:authorization (basic-auth-header email password)}
:response-format (ajax/json-response-format {:keywords? true})
:on-success [:login-success]
:on-failure [:login-failure]}}))
(re-frame/reg-event-fx
:login-success
(fn [{:keys [db]} [_ response]]
(let [token (:access_token response)]
{:dispatch [:navigate :channel-list]
:db (assoc db :access-token token)
:set-local-store ["access_token" token]})))
- Subscriptions allow to read/query the db.
- They help to make your views dumber by encapsulating all data
processing.
- They allow to decouple the view from the app-db schema.
(re-frame/reg-sub
:authenticated?
(fn [db]
(boolean (:access-token db))))
(re-frame/reg-sub
:user-info
(fn [db]
(token/decode (:access-token db))))
(re-frame/reg-sub
:avatar
(fn [_ _] (re-frame/subscribe [:user-info]))
(fn [{:keys [email avatar]} _]
(if avatar
avatar
(gravatar email))))
(defn user-info-view []
(when @(re-frame/subscribe [:authenticated?])
(let [{name :name} @(re-frame/subscribe [:user-info])
avatar @(re-frame/subscribe [:avatar])]
[:header.navbar-item.is-hoverable.has-dropdown
[:a.navbar-link
[:img {:src avatar}]]
[:div.navbar-dropdown
[:div.navbar-item.has-text-grey name]
[:hr.navbar-divider]
[:a.navbar-item
{:on-click #(re-frame/dispatch [:logout])} "Logout"]]])))
