Skip to content

Instantly share code, notes, and snippets.

@reedho
Created September 28, 2021 10:13
Show Gist options
  • Save reedho/b542e21c57434a26a35d5c0eedf3fffe to your computer and use it in GitHub Desktop.
Save reedho/b542e21c57434a26a35d5c0eedf3fffe to your computer and use it in GitHub Desktop.
Rumext ReactRouter v5
;; 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