Created
September 28, 2021 10:13
-
-
Save reedho/b542e21c57434a26a35d5c0eedf3fffe to your computer and use it in GitHub Desktop.
Rumext ReactRouter v5
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
;; https://reactrouter.com/web/example/auth-workflow | |
;; ported to cljs with rumext | |
;; 28-Sep-2021 | |
;; Ridho | |
(ns my.web.app | |
(:require ["react" :as react :refer [createContext useContext]] | |
["react-dom" :as react-dom] | |
[rumext.alpha :as mf] | |
[applied-science.js-interop :as j] | |
["react-router-dom" :rename {BrowserRouter Router} | |
:refer [Switch Route Link Redirect | |
useRouteMatch useParams useHistory useLocation]] | |
)) | |
(def fake-auth | |
(let [x (atom false)] | |
{:sign-in (fn [cb] | |
(reset! x true) | |
(js/setTimeout cb 300)) | |
:sign-out (fn [cb] | |
(reset! x true) | |
(js/setTimeout cb 200))})) | |
(def authContext (createContext)) | |
(defn useAuth | |
[] | |
(useContext authContext)) | |
(defn useProvideAuth | |
[] | |
(let [user (mf/use-state nil)] | |
{:user @user | |
:sign-in (fn [cb] | |
((:sign-in fake-auth) (fn [] | |
(reset! user "Ridho") | |
(cb)))) | |
:sign-out (fn [cb] | |
((:sign-out fake-auth) (fn [] | |
(reset! user nil) | |
(cb))))})) | |
(mf/defc ProvideAuth | |
[{:keys [children]}] | |
(let [auth (useProvideAuth)] | |
[:> (.-Provider authContext) {:value auth} | |
children | |
])) | |
(mf/defc AuthButton | |
[] | |
(let [history (useHistory) | |
{:keys [user sign-in sign-out]} (useAuth)] | |
(if user | |
[:p | |
"Welcome! " user " " | |
[:button {:on-click (fn [] | |
(sign-out (fn [] | |
(.push history "/"))))} | |
"Signout"]] | |
;; --else | |
[:p "You are not logged in."]))) | |
(mf/defc PrivateRoute | |
[{:keys [children] :as props}] | |
(let [{:keys [user]} (useAuth)] | |
(mf/element | |
Route | |
(merge | |
(dissoc props :children) | |
{:render | |
(fn [route] | |
(js/console.log "ROUTE" route) | |
(let [location (j/get route :location)] | |
(if user | |
children | |
;; --else | |
(mf/element Redirect {:to #js {:pathname "/login" | |
:state #js {:from location}}}))))})))) | |
(mf/defc PublicPage | |
[] | |
[:h3 "Public"]) | |
(mf/defc ProtectedPage | |
[] | |
[:h3 "Protected"]) | |
(mf/defc LoginPage | |
[] | |
(let [history (useHistory) | |
location (useLocation) | |
{:keys [sign-in]} (useAuth) | |
from (j/get-in location [:state :from] | |
#js {:pathname "/"}) | |
login (fn [] | |
(sign-in (fn [] | |
(.replace history from)))) | |
] | |
[:div | |
[:p "You must log in to view the page at " (j/get from :pathname)] | |
[:button {:on-click login} "Log in"]] | |
)) | |
(mf/defc AuthExample | |
[] | |
[:> ProvideAuth {} | |
[:> Router {} | |
[:div | |
[:& AuthButton] | |
[:ul | |
[:li [:> Link {:to "/public"} "Public Page"]] | |
[:li [:> Link {:to "/protected"} "Protected Page"]]] | |
[:> Switch {} | |
[:> Route {:path "/public"} [:& PublicPage]] | |
[:> Route {:path "/login"} [:& LoginPage]] | |
[:> PrivateRoute {:path "/protected"} [:& ProtectedPage]]]]]]) | |
;; --- MAIN --- | |
(defn ^:dev/after-load start [] | |
(println "Starting at" (js/Date.)) | |
(mf/mount (mf/element AuthExample) | |
(js/document.getElementById "root"))) | |
(defn ^:export init [] | |
(start)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment