Skip to content

Instantly share code, notes, and snippets.

@martinklepsch
Created January 13, 2017 06:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martinklepsch/8e8a924a9e2b3293688530e905fd3e4e to your computer and use it in GitHub Desktop.
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.
(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