This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-08-16
Channels
- # admin-announcements (2)
- # bangalore-clj (3)
- # beginners (15)
- # boot (303)
- # carry (18)
- # cider (7)
- # cljs-dev (222)
- # cljsrn (103)
- # clojure (196)
- # clojure-czech (2)
- # clojure-russia (69)
- # clojure-spec (21)
- # clojure-uk (48)
- # clojurescript (68)
- # cursive (18)
- # datomic (185)
- # events (1)
- # hoplon (2)
- # lambdaisland (1)
- # leiningen (1)
- # mount (10)
- # off-topic (1)
- # om (14)
- # onyx (154)
- # parinfer (1)
- # pedestal (3)
- # planck (5)
- # protorepl (9)
- # re-frame (17)
- # reagent (27)
- # ring (2)
- # specter (58)
- # test-check (1)
- # testing (7)
- # untangled (59)
- # yada (35)
how do you handle multiple controllers btw @metametadata ?
if a component dispatches signals and the intended controller may be any one of N.. what do you do? Does a "parent" controller need to know the "child" controllers?
Hey @kauko! Could you please give an example of "multiple controllers"? Because, stricly speaking, for each app there's only a single controller.
Maybe you mean how one can define this controller using more smaller ones (i.e. like redux does with reducers)?
Yeah, I agree. It's something I thought about but didn't prescribe in the framework yet.
There could be different solutions. On top of my head: - define controller as multimethod, this way you can scatter signal processing across many files easily; but there may be problems with pattern matching now?.. - "Flux way": ensemble a controller from smaller controllers; when a "parent" receives a signal it sends the signals to all the children; this is also how Redux works if I'm not mistaken; - the "chain of responsibility"-kinda approach: ensemble controller from the smaller controllers; when it receives a signal it first sends it to the first child, if it wasn't handled - sends it to the second child, etc. until someone is able to handle the signal
I recall I liked the last approach the most
because in this case you can easily throw an exception if no handler was found for a signal. Redux in such situations silently ignores the error.
Just in case, here's the Redux pattern explained by author: https://stackoverflow.com/questions/35667775/state-in-redux-react-app-has-a-property-with-the-name-of-the-reducer/35674297#35674297
And here's a snippet for my liked approach:
;; spec
; only one controller will handle a signal
:control (ui/either #{app-control
router/control
files-logic/control
settings-logic/control})
(ns frontend.settings.logic
(:require [cljs.core.match :refer-macros [match]]))
(defn control
[model signal dispatch-signal dispatch-action]
(match signal
[:on-select-theme id] (dispatch-action [:select-theme id])
; ...
:else :bypass)) ; <-------------------------------------------- let other controller handle the unknown signal
(defn either
"Returns a function of any args which calls functions one by one while :bypass is returned."
[fns]
(fn either-fn [& args]
(loop [f (first fns)
next-fns (rest fns)]
(when (nil? f)
(throw (ex-info (str "No function was able to handle passed args: " (pr-str args))
{})))
(let [result (apply f args)]
(if (= result :bypass)
(recur (first next-fns) (rest next-fns))
result)))))
Yeah, I think that could work. It's important that the ability to give components custom controllers is retained, for testing for example. So avoid some register-controller
functions that add a controller to some global thingy
and when I work on my view component and add some new signals, I want to add it to one place, not several places
Sounds reasonable!
this either
function can be used to split a reconciler as well