Created
June 10, 2019 15:56
-
-
Save danielneal/a09770486a0f0d53367d775b8ccdff93 to your computer and use it in GitHub Desktop.
Shadow / hx / React Native / expo
This file contains hidden or 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 test.app | |
(:require | |
["expo" :as ex] | |
["react-native" :as rn] | |
["react" :as react] | |
[test.db :as db] | |
[hx.react :as hx :refer [defnc]] | |
[hx.hooks :as hooks] | |
[shadow.expo :as expo])) | |
(defnc Greet [] | |
;; use React Hooks for state management | |
(let [{:person/keys [name]} (db/useQuery [:person/name]) | |
dispatch! (db/useDispatch)] | |
[:<> | |
[rn/Text name] | |
[rn/TextInput {:onChangeText (fn [text] (dispatch! [:person/set-name text]))}]])) | |
(defnc App [] | |
[:provider db/provider | |
[rn/View {:style {:padding 8}} | |
[Greet]]]) | |
(defn start | |
{:dev/after-load true} | |
[] | |
(expo/render-root (hx/f [App]))) | |
(defn init [] | |
(start)) | |
This file contains hidden or 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 test.db | |
(:require [hx.react :as hx] | |
[hx.hooks :as hooks] | |
["react" :as react])) | |
;; little query engine over nested maps | |
(defn paths | |
([q] | |
(paths [] {} q)) | |
([current-path m q] | |
(letfn [(paths-map | |
[current-path m q] | |
(apply merge (for [[k v] q] | |
(paths (conj current-path k) {} v)))) | |
(paths-vec | |
[current-path m q] | |
(apply merge (for [v q] | |
(if (map? v) | |
(paths-map current-path {} v) | |
(paths (conj current-path v) {} v)))))] | |
(cond | |
(map? q) (paths-map current-path m q) | |
(vector? q) (paths-vec current-path m q) | |
:else {q current-path})))) | |
(defn query-fn | |
[q] | |
(let [paths (paths q)] | |
(fn [db] | |
(reduce-kv (fn [m k v] (assoc m k (get-in db v))) {} paths)))) | |
(defn query | |
[db q] | |
(let [f (query-fn q)] | |
(f db))) | |
;; (query {:a 1 :b 2 :c {:d 3}} [:a]) => {:a 1}) | |
;; (query {:a 1, :b 2 :c {:d 3}} [:a {:b :product/id}] | |
(def context (hx/create-context)) | |
;; Subscriptions - provide a hook that returns some state that | |
;; runs query over db and updates state when it changes | |
(defn useQuery | |
[q] | |
(let [db (hooks/useContext context) | |
[result updateResult] (react/useState (query @db q)) | |
k (gensym)] | |
(hooks/useEffect | |
(fn [] | |
(add-watch db k (fn [_ _ _ state] | |
(let [new-result (query state q)] | |
(when (not= new-result result) | |
(updateResult new-result))))) | |
(fn [] | |
(remove-watch db k))) | |
#js [q]) | |
result)) | |
;; Dispatch - provide a hook that returns a fn to swap! the db | |
(defmulti handle-event (fn [db [type & _]] type)) | |
(defmethod handle-event :person/set-name | |
[db [_ v]] | |
(assoc db :person/name v)) | |
;; Context Provider | |
(def app-db (atom {})) | |
(def provider | |
{:context context | |
:value app-db}) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment