From fd0bc933e97b72c39f4d4f8df055df99d8a34d61 Mon Sep 17 00:00:00 2001 From: rcmerci Date: Tue, 7 Jan 2025 14:35:59 +0800 Subject: [PATCH] refactor: make react hooks compatible with cljs builtin types --- .clj-kondo/config.edn | 1 + src/main/frontend/components/block.cljs | 5 ++- src/main/frontend/hooks.cljs | 50 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 src/main/frontend/hooks.cljs diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn index fa586af1f0..0b7ea9fd80 100644 --- a/.clj-kondo/config.edn +++ b/.clj-kondo/config.edn @@ -122,6 +122,7 @@ frontend.handler.route route-handler frontend.handler.search search-handler frontend.handler.ui ui-handler + frontend.hooks hooks frontend.idb idb frontend.loader loader frontend.mixins mixins diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index 6ae6887712..ac72ddf55d 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -55,6 +55,7 @@ [frontend.handler.route :as route-handler] [frontend.handler.ui :as ui-handler] [frontend.handler.whiteboard :as whiteboard-handler] + [frontend.hooks :as hooks] [frontend.mixins :as mixins] [frontend.mobile.intent :as mobile-intent] [frontend.mobile.util :as mobile-util] @@ -2750,11 +2751,11 @@ (let [[result set-result!] (rum/use-state nil) repo (state/get-current-repo) [status-history time-spent] result] - (rum/use-effect! + (hooks/use-effect! (fn [] (p/let [result (db-async/ time-spent 0)) [:div.text-sm.time-spent.ml-1 (shui/button diff --git a/src/main/frontend/hooks.cljs b/src/main/frontend/hooks.cljs new file mode 100644 index 0000000000..c109e30a17 --- /dev/null +++ b/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)