re-frame

(repo / README)

https://day8.github.io/re-frame/

  • 간락한 개념.
DB ->
  뷰 ->
    Reagent ->
      React ->
        렌더링.
        <- 이벤트 발생.
      <- 이벤트 큐잉
    <- 이벤트 처리 (인터셉터와 함께), 이펙트 발생.
  <- 이펙터 처리.
DB
  • 키워드로 보는 개념.
app-db ->
  [:hiccup] ->
    (r/render-component component dom-root) ->
    (rf/subsribe query-id) ->
      React ->
        Dom ->
          Render
          <- (rf/dispatch event)
          <- [event ...]
        <- (rf/reg-event-fx event-id [interceptor ...] (fn [cofx event]))
          <- rf.cofx/inject-db :before
          <- (rf/->interceptor :before)
          <- (fn [cofx event] ...)
          <- (rf/->interceptor :after)
          <- rf.fx/do-fx :after
          <- [effect ...]
    <- (rf/reg-fx effect-id (fn [event-value] ...)
  <- (rf/reg-sub query-id (fn [db] ...))
  <- (rf/reg-sub query-id (fn [db] ...))
app-db

용어설명

kind reg-*

register handler
:event-db
:event-fx
:event-ctx
:sub
:sub-raw
:fx
:cofx

drawing board
reg-view
reg-interceptor

(rf/reg-event-db
   :event-id
   (fn [db event]
     (assoc db :some :thing)))

(rf/reg
  {:kind  :event-db
   :id    :event-id
   :fn    (fn [db event]
            (assoc db :some :thing))})

(rf/reg
  [{:kind :event-db ...}
   {:kind :event-db ...}
   {:kind :event-fx ...}
   {:kind :sub ...])

Registrar

Each entry stored in the registrar will become a map instead of just a handler.

Map keys:

:kind - somehow redundant
:id
:doc
:line
:ns
:doc
:fn the handler

`re-com` is a library which supplies reusable Reagent widgets. And widgets, like a datepicker, are the simplest kind of components.
`re-com` components are reusability because they take an input stream of data and they

`def-view`: TODO

DB : (app-db / db)

{...}

event

[event-id & args]

Event (event)

Effect (effect / fx)

  • https://github.com/Day8/re-frame/blob/master/docs/API.md
  • 내장 이펙트
[:db `db`]

[:dispatch `event`]

[:dispatch-n [(nil | `event`) ...]]

[:dispatch-later [ (nil | {:ms `int` :dispatch `event`}) ...]]

[:deregister-event-handler `event-id`]

[:deregister-event-handler [`event-id` ...]]

Coeffect (coeffect / cofx)

  • http://tomasp.net/coeffects/
  • the data your event handler requires from the world in order to do its computation (aka side-causes)
  • 내장 코-이펙트
{
 :local-store `local-store`
 :db `db` ;; `current-app-state`
}

contextmap (context, ctx)

{:coeffects {:event [:some-id :some-param]
             :db    <original contents of app-db>}

 :effects   {:db    <new value for app-db>
             :dispatch  [:an-event-id :param1]}

 :queue     <a collection of further interceptors>
 :stack     <a collection of interceptors already walked>}

raise

(rf/dispatch `event`)

(rf/dispatch-sync `event`)

queueing

[event1 event2 event3 ...]

event-routeter

(rf/reg-event-fx
  `event-key`
  (fn [`cofx` `event`]
    `effect`))
;;=> {...} => [[`effect-key` `effect-value`] ...]

(rf/reg-event-fx
  `event-key`
  [`interceptor` ...]
  (fn [`cofx` `event`]
    `effect`))
;;=> {...} => [[`effect-key` `effect-value`] ...]

(reg-event-db
  `event-key`
  (fn [`db` `event`]
    `new-db`))
;;=> {:db `new-db`} => [[:db `new-db`]]
(reg-event-db
  `event-key`
  (fn [{:key [db]} `event`]
    (assoc db :a 10)))

(reg-event-fx
  `event-key`
  (fn [{:key [db]} `event`]
    {:db (assoc db :a 10)}))

(reg-event-ctx
  `event-key`
  (fn [`context-map` `event`]
    `context-map`)

effect-routeter

[[`effect-key` `effect-value`] ...]

apply effect

  • built-in : :db, :dispatch, ``
(rf/reg-fx
  `effect-key`
  (fn [`effect-value`]
     ...))

interceptor

  • built-in
    • debug
    • trim-v
  • built-in factory
    • enrich
    • path
    • after
    • inject-cofx
  • built-in more : std_interceptors.clj
{:id      `cofx-id`
 :before  (fn [context] ...)
 :after   (fn [context] ...)}

(rf/inject-cofx `cofx-id` arg)

(rf/->interceptor
 :id     `cofx-id`
 :before handle-context
 :after  handle-context)

(reg-cofx
   `cofx-id`
   (fn [`cofx` arg]
      `cofx`))

reg-sub / subscribe

{:name "Bruce"}

(rf/reg-sub
  :get-name
  (fn [db _]
    (name db))) => "Bruce"

(rf/reg-sub
  :greeting
  (fn [db _]
    (rf/subscribe :get-name))
  (fn [name _]
    (st "Hello, " name))) => "Hello, Bruce"

@(rf/subscribe :greeting) => "Hello, Bruce"

  1. (reg-sub
       :test-sub
       (fn [db [_]] db))

  ;; The value in app-db is passed to the computation function as the 1st argument.

  2. (reg-sub
       :a-b-sub
       (fn [q-vec d-vec]
         [(subs/subscribe [:a-sub])
          (subs/subscribe [:b-sub])])
       (fn [[a b] [_]] {:a a :b b}))

  ;;  Two functions provided. The 2nd is computation function, as before. The 1st
  ;;  is returns what `input signals` should be provided to the computation. The
  ;;  `input signals` function is called with two arguments: the query vector
  ;;  and the dynamic vector. The return value can be singleton reaction or
  ;;  a sequence of reactions.

  3. (reg-sub
       :a-b-sub
       :<- [:a-sub]
       :<- [:b-sub]
       (fn [[a b] [_]] {:a a :b b}))```
(let [value @(rf/subsribe `query-id`)])



(rf/reg-sub
  `query-id`
  (fn [db event] ; computation-fn
    value))

(rf/reg-sub
  `query-id`
  (fn [query-vec dynamic-vec]
    [(subscribe [:a-sub])
     (subscribe [:b-sub])])
  (fn [[a b] query-vec]
    ....))

Ref