Browse Source

refactor: make react hooks compatible with cljs builtin types

rcmerci 1 year ago
parent
commit
fd0bc933e9
3 changed files with 54 additions and 2 deletions
  1. 1 0
      .clj-kondo/config.edn
  2. 3 2
      src/main/frontend/components/block.cljs
  3. 50 0
      src/main/frontend/hooks.cljs

+ 1 - 0
.clj-kondo/config.edn

@@ -122,6 +122,7 @@
              frontend.handler.route route-handler
              frontend.handler.route route-handler
              frontend.handler.search search-handler
              frontend.handler.search search-handler
              frontend.handler.ui ui-handler
              frontend.handler.ui ui-handler
+             frontend.hooks hooks
              frontend.idb idb
              frontend.idb idb
              frontend.loader loader
              frontend.loader loader
              frontend.mixins mixins
              frontend.mixins mixins

+ 3 - 2
src/main/frontend/components/block.cljs

@@ -55,6 +55,7 @@
             [frontend.handler.route :as route-handler]
             [frontend.handler.route :as route-handler]
             [frontend.handler.ui :as ui-handler]
             [frontend.handler.ui :as ui-handler]
             [frontend.handler.whiteboard :as whiteboard-handler]
             [frontend.handler.whiteboard :as whiteboard-handler]
+            [frontend.hooks :as hooks]
             [frontend.mixins :as mixins]
             [frontend.mixins :as mixins]
             [frontend.mobile.intent :as mobile-intent]
             [frontend.mobile.intent :as mobile-intent]
             [frontend.mobile.util :as mobile-util]
             [frontend.mobile.util :as mobile-util]
@@ -2750,11 +2751,11 @@
     (let [[result set-result!] (rum/use-state nil)
     (let [[result set-result!] (rum/use-state nil)
           repo (state/get-current-repo)
           repo (state/get-current-repo)
           [status-history time-spent] result]
           [status-history time-spent] result]
-      (rum/use-effect!
+      (hooks/use-effect!
        (fn []
        (fn []
          (p/let [result (db-async/<task-spent-time repo (:db/id block))]
          (p/let [result (db-async/<task-spent-time repo (:db/id block))]
            (set-result! result)))
            (set-result! result)))
-       [(:db/id (:logseq.task/status block))])
+       [(:logseq.task/status block)])
       (when (and time-spent (> time-spent 0))
       (when (and time-spent (> time-spent 0))
         [:div.text-sm.time-spent.ml-1
         [:div.text-sm.time-spent.ml-1
          (shui/button
          (shui/button

+ 50 - 0
src/main/frontend/hooks.cljs

@@ -0,0 +1,50 @@
+(ns frontend.hooks
+  "React custom hooks."
+  (:refer-clojure :exclude [ref deref])
+  (:require [datascript.impl.entity :refer [Entity]]
+            [rum.core :as rum]))
+
+(defn- safe-dep
+  "js/React use `js/Object.is` to compare dep-value and its previous value.
+  Some cljs built-in types(keyword, symbol, uuid) would not be identical, even they are value-equal"
+  [dep]
+  (if (contains? #{"string" "number" "boolean" "null"} (goog/typeOf dep))
+    dep
+    (cond
+      (or (keyword? dep)
+          (symbol? dep)
+          (uuid? dep))
+      (str dep)
+
+      (instance? Entity dep)
+      ;; NOTE: only :db/id is considered, without taking the entity-db into account
+      ;; so, same entity-id but different db will be "equal" here
+      (:db/id dep)
+
+      :else
+      (throw (ex-info (str "Not supported dep type:" (type dep)) {:dep dep})))))
+
+(defn use-memo
+  ([f] (rum/use-memo f))
+  ([f deps] (rum/use-memo f (map safe-dep deps))))
+
+(defn use-effect!
+  ([setup-fn] (rum/use-effect! setup-fn))
+  ([setup-fn deps] (rum/use-effect! setup-fn (map safe-dep deps))))
+
+(defn use-layout-effect!
+  ([setup-fn] (rum/use-layout-effect! setup-fn))
+  ([setup-fn deps] (rum/use-layout-effect! setup-fn (map safe-dep deps))))
+
+(defn use-callback
+  ([callback] (rum/use-callback callback))
+  ([callback deps] (rum/use-callback callback (map safe-dep deps))))
+
+;;; unchanged hooks, link to rum/use-xxx directly
+(def use-ref rum/use-ref)
+(def create-ref rum/create-ref)
+(def deref rum/deref)
+(def set-ref! rum/set-ref!)
+
+(def use-state rum/use-state)
+(def use-reducer rum/use-reducer)