Skip to content

Instantly share code, notes, and snippets.

@aiba
Created May 17, 2020 13:00
Show Gist options
  • Save aiba/209243d709eb2cde953f31e0390ec330 to your computer and use it in GitHub Desktop.
Save aiba/209243d709eb2cde953f31e0390ec330 to your computer and use it in GitHub Desktop.
use-url-linking hook for react-navigation
(ns myapp.url-linking
(:require ["@react-navigation/native" :as rnav]
["react" :as react]
["react-native" :as rn]
[applied-science.js-interop :as j]
[cemerick.url :as url]
[clojure.string :as str]
[helix.core :as helix]
[helix.hooks :as hooks]
[kitchen-async.promise :as p]
[taoensso.timbre :as log]))
(defonce root-nav-ref (react/createRef))
(defn navigate! [screen params]
(if-let [nav (j/get root-nav-ref :current)]
(j/call nav :navigate screen params)
(log/warn "root-nav-ref nil")))
;; returns [path opts-map]
(defn- parse-query [p]
(let [[p q] (str/split p #"\?")]
[p (url/query->map q)]))
(defn- path-parts->params [path-parts]
(when-let [p (first path-parts)]
(let [[p params] (parse-query p)]
{:screen p
:params (merge {:initial false} ;; default
params
(path-parts->params (rest path-parts)))})))
(defn navigate-to-path! [path]
(assert (= (first path) "/")) ;; absolute path
(let [parts (str/split (subs path 1) #"/")
params (path-parts->params parts)]
(navigate! (:screen params) (clj->js (:params params)))))
(defn- use-url-linking []
(let [url->path (fn [url] (subs url (+ 2 (str/index-of url ":"))))
nav-to-url! (fn [url] (navigate-to-path! (url->path url)))
handle-url-event (fn [event]
(let [url (j/get event :url)]
(log/info "Linking URL event:" url)
(nav-to-url! url)))]
(hooks/use-effect :once
(-> (j/call rn/Linking :getInitialURL)
(p/then (fn [url]
(when url
(log/info "Linking initial URL:" url)
(nav-to-url! url))))
(p/then (fn [_]
(j/call rn/Linking :addEventListener "url" handle-url-event))))
(fn []
(j/call rn/Linking :removeEventListener "url" handle-url-event)))))
(helix/defnc AppRootContainer []
(use-url-linking)
[rnav/NavigationContainer {:ref root-nav-ref}
;; screens here
])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment