Created
January 13, 2017 06:19
-
-
Save martinklepsch/8e8a924a9e2b3293688530e905fd3e4e to your computer and use it in GitHub Desktop.
Rum components to start/stop com.stuartsierra.component systems and inject them into React context.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns org.martinklepsch.rum-system | |
"Rum components to start/stop com.stuartsierra.component systems and inject them into React context." | |
(:refer-clojure :exclude [comp]) | |
(:require [rum.core :as rum] | |
[goog.object :as gobj] | |
[com.stuartsierra.component :as component])) | |
(def context-k (-> (str ::get-sys) (subs 1))) | |
(def context-types {context-k js/React.PropTypes.func}) | |
(defn component | |
"Injects selected components `ks` into component state. | |
Use `comp` function to obtain a component from component state." | |
[& ks] | |
{:class-properties {:contextTypes context-types} | |
:will-mount (fn component-will-mount [s] | |
(let [get-sys (-> s :rum/react-component (gobj/get "context") (gobj/get context-k))] | |
(reduce #(assoc-in %1 [::components %2] (get (get-sys) %2)) s ks)))}) | |
(defn system | |
"Starts and injects the passed component system into the React context. | |
Also adds the system to the components state under ::system. | |
The system will be stopped as part of :will-unmount." | |
[sys] | |
{:class-properties {:childContextTypes {context-k js/React.PropTypes.func}} | |
:child-context (fn system-child-context [s] {context-k (fn [] (get s ::system))}) | |
:will-mount (fn system-will-mount [s] | |
(let [started-sys (component/start sys)] | |
(js/console.info "System started") | |
(assoc s ::system started-sys))) | |
:will-unmount (fn system-will-unmount [s] | |
(js/console.info "Stopping system...") | |
(component/stop (get s ::system)))}) | |
(defn comp | |
"Find component `comp-id` in `component-state`. Throw an exception if not present." | |
[component-state comp-id] | |
(or (get-in component-state [::components comp-id]) | |
(throw (ex-info (str "No component found! Maybe you forgot a (component " comp-id ") mixin?") | |
{:component-id comp-id :components (keys (::components component-state))})))) | |
(defn get-system [rum-state] | |
(let [get-system (-> rum-state :rum/react-component (gobj/getValueByKeys "context" context-k))] | |
(assert get-system "No system getter found in component, is contextTypes set properly?") | |
(get-system))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment