Last active
May 14, 2020 06:39
-
-
Save frankiesardo/d135c73d74695d83277c4294a987006f to your computer and use it in GitHub Desktop.
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 example.app | |
(:require | |
["expo" :as ex] | |
["react-native" :as rn] | |
["react" :as react :rename {createElement $}] | |
[shadow.expo :as expo])) | |
(defn useEffectiveReducer [reducer handlers initial-state] | |
(let [[state set-state] (react/useState initial-state) | |
[queue update-queue] (react/useReducer (fn [state action] (action state)) []) | |
dispatch (fn [action] | |
(let [{:keys [state] :as effect} (reducer state action)] | |
(when state ;; Todo: check for not= state new-state. Also it can be nil so check for contains? | |
(set-state state)) | |
(when-let [effect (not-empty (dissoc effect :state))] | |
(update-queue #(conj % effect)))))] | |
(react/useEffect | |
(fn [] | |
(println :Effect! queue) | |
(doseq [effect queue | |
[type payload] effect | |
;; Todo: check for nil | |
:let [handler (get handlers type)]] | |
(handler dispatch payload)) | |
(update-queue (constantly [])) | |
(fn [])) | |
#js [queue]) | |
[state dispatch])) | |
(defmulti reducer (fn [state {:keys [type payload]}] type)) | |
(defmethod reducer ::login [state {{:keys [email password]} :payload :as action}] | |
{:state "Loading..." | |
:http {:url :login-url | |
:params (str email ":" password) | |
:callback ::login-cb} | |
:log action}) | |
(defmethod reducer ::login-cb [state {{:keys [success body]} :payload :as action}] | |
{:state (if success | |
(str "Your name is " (get-in body [:profile :name])) | |
"Call to server failed") | |
:log action}) | |
(defmethod reducer ::logout [state action] | |
{:state "Loading..." | |
:http {:url :logout-url | |
:callback ::logout-cb} | |
:log action}) | |
(defmethod reducer ::logout-cb [state {{:keys [success]} :payload :as action}] | |
{:state "Logged out" | |
:log action}) | |
(defn http [dispatch {:keys [callback] :as payload}] | |
(js/setTimeout | |
#(do (println "Calling server.." payload) | |
(dispatch {:type callback | |
:payload {:success true | |
:status 200 | |
:body {:profile {:name "Alice"}}}})) | |
1000)) | |
(defn log [dispatch payload] | |
(println payload)) | |
(defn App [] | |
(let [[state dispatch] (useEffectiveReducer reducer {:http http :log log} "Logged out")] | |
;; Todo: create useReloadAtom effect | |
(println :Rendering state) | |
($ rn/View #js {:style #js {:flex 1}} | |
($ rn/Text #js {} (str "Current status: " state)) | |
($ rn/Button #js {:title "Login" | |
:onPress #(dispatch {:type ::login | |
:payload {:email "foo@gmail.com" | |
:password "123"}})}) | |
($ rn/Button #js {:title "Logout" | |
:onPress #(dispatch {:type ::logout})})))) | |
(defn start | |
{:dev/after-load true} | |
[] | |
(expo/render-root ($ App))) | |
(defn ^:export init [] | |
(start)) | |
(defn stop | |
{:dev/before-load true} | |
[] | |
(js/console.log "stop")) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment