8000 refactor(react): move useentity to new cache · homebaseio/homebase-react@605b9c7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 605b9c7

Browse files
refactor(react): move useentity to new cache
1 parent 4622e99 commit 605b9c7

File tree

8 files changed

+165
-74
lines changed

8 files changed

+165
-74
lines changed

deps.edn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
reagent/reagent {:mvn/version "1.0.0"}
66
inflections/inflections {:mvn/version "0.13.2"}
77
binaryage/devtools {:mvn/version "1.0.2"}
8-
homebaseio/datalog-console {:git/url "https://github.com/homebaseio/datalog-console" :sha "97d5e5eb8994124ec8dc0029b33f2e88257b39b2"}
8+
homebaseio/datalog-console {:git/url "https://github.com/homebaseio/datalog-console" :sha "fc4cf9ba968e995a67aae1816670adb78a81451d"}
99
;; homebaseio/datalog-console {:local/root "../datalog-console"}
1010
nano-id {:mvn/version "1.0.0"}
1111
camel-snake-kebab/camel-snake-kebab {:mvn/version "0.4.2"}}}

src/dev/example/js/todo.jsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ const Todo = React.memo(({ id }) => {
163163
 · 
164164
<TodoDelete todo={todo} />
165165
</div>
166-
<small style={{ color: 'grey' }}>{todo.get('createdAt').toLocaleString()}</small>
166+
<small style={{ color: 'grey' }}>{todo.get('createdAt')?.toLocaleString()}</small>
167167
</div>
168168
)
169169
})
@@ -237,7 +237,8 @@ const TodoFilters = () => {
237237
type="checkbox"
238238
checked={filters.get('showCompleted')}
239239
onChange={(e) =>
240-
transact([{ todoFilter: { id: filters.get('id'), showCompleted: e.target.checked } }])}
240+
transact([{ todoFilter: { id: filters.get('id'), showCompleted: e.target.checked } }])
241+
}
241242
/>
242243
</label>
243244
&nbsp;·&nbsp;

src/dev/example/js_compiled/todo.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ const Todo = /*#__PURE__*/_react.default.memo(({
171171
style: {
172172
color: 'grey'
173173
}
174-
}, todo.get('createdAt').toLocaleString()));
174+
}, todo.get('createdAt')?.toLocaleString()));
175175
});
176176

177177
const TodoCheck = ({

src/dev/example/reagent/counter.cljs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
[datascript.core :as d]
55
[homebase.reagent :as hbr])
66
(:require-macros
7-
[devcards.core :refer [defcard-rg]]))
7+
[devcards.core :refer [defcard-rg defcard-doc]]
8+
[dev.macros :refer [inline-resource]]))
89

910
(def db-conn (d/create-conn {}))
1011
(hbr/connect! db-conn)
@@ -20,4 +21,7 @@
2021
"Increment"]]])))
2122

2223
(defcard-rg counter-example
23-
counter)
24+
counter)
25+
26+
(defcard-doc
27+
(str "```clojure\n" (inline-resource "src/dev/example/reagent/counter.cljs") "\n```"))

src/dev/example/reagent/todo.cljs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
[reagent.core :as r]
66
[homebase.reagent :as hbr])
77
(:require-macros
8-
[devcards.core :refer [defcard-rg]]))
8+
[devcards.core :refer [defcard-rg defcard-doc]]
9+
[dev.macros :refer [inline-resource]]))
910

1011
(def db-conn (d/create-conn {:todo/project {:db/type :db.type/ref
1112
:db/cardinality :db.cardinality/one}
@@ -179,4 +180,7 @@
179180
[todos filters]])))
180181

181182
(defcard-rg todo-example
182-
todo-app)
183+
todo-app)
184+
185+
(defcard-doc
186+
(str "```clojure\n" (inline-resource "src/dev/example/reagent/todo.cljs") "\n```"))

src/homebase/js.cljs

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,9 @@
136136
{} (js->clj lookup))))
137137

138138
(defmulti js->entity-lookup type)
139-
(defmethod js->entity-lookup js/Number [lookup] lookup)
140139
(defmethod js->entity-lookup js/Object [lookup] (first (js->object-lookup lookup)))
140+
(defmethod js->entity-lookup js/Number [lookup] lookup)
141+
(defmethod js->entity-lookup :default [lookup] lookup)
141142

142143
(comment
143144
(js->tx nil (clj->js [{:project {:array [[1] [2 {:k "v"}]]}}]))
@@ -228,14 +229,21 @@
228229
(reduced (namespace k))))
229230
nil (keys entity)))
230231

231-
(defn js-get [^de/Entity entity name]
232+
(defn js-guess-attr
233+
"Takes an entity and a js name string and trys to guess the
234+
ns and cljs name of the corresponding attribute in the given entity.
235+
236+
Assumes that the entity was created by homebase.js and conforms to its conventions.
237+
238+
Returns a keyword."
239+
[^de/Entity entity name]
232240
(case name
233-
"id" (:db/id entity)
234-
"ident" (:db/ident entity)
235-
"identity" (:db/ident entity)
241+
"id" :db/id
242+
"ident" :db/ident
243+
"identity" :db/ident
236244
(let [maybe-ns (guess-entity-ns entity)
237245
k (when maybe-ns (js->key maybe-ns name))]
238-
(when k (get entity k)))))
246+
k)))
239247

240248
(declare
241249
Entity
@@ -284,9 +292,10 @@
284292

285293
(defn lookup-entity
286294
"Takes a homebase.js/Entity and a seq of attributes. Looks up the attribute path on the entity. Returns a scalar or homebase.js/Entity or js/Array of scalars or Entities."
287-
([entity attrs] (lookup-entity entity attrs false))
288-
([entity attrs nil-attrs-if-not-in-db?] (lookup-entity entity attrs nil-attrs-if-not-in-db? nil))
289-
([entity attrs nil-attrs-if-not-in-db? get-cb]
295+
([entity attrs] (lookup-entity entity attrs false nil nil))
296+
([entity attrs nil-attrs-if-not-in-db?] (lookup-entity entity attrs nil-attrs-if-not-in-db? nil nil))
297+
([entity attrs nil-attrs-if-not-in-db? get-cb] (lookup-entity entity attrs nil-attrs-if-not-in-db? get-cb nil))
298+
([entity attrs nil-attrs-if-not-in-db? get-cb after-lookup]
290299
(humanize-error
291300
#(humanize-get-error % entity)
292301
(fn []
@@ -295,8 +304,13 @@
295304
(if-not acc
296305
nil
297306
(let [attr (keywordize attr)
298-
getter-fn (if (keyword? attr) get js-get)
299-
getter-fn (comp (partial entity->js {:Entity/get-cb get-cb})
307+
getter-fn (fn [entity attr]
308+
(let [attr (if (keyword? attr) attr (js-guess-attr entity attr))
309+
result (when attr (get entity attr))]
310+
(when (and after-lookup attr) (after-lookup {:entity entity :attr attr :result result }))
311+
result))
312+
getter-fn (comp (partial entity->js {:Entity/get-cb get-cb
313+
::after-lookup after-lookup})
300314
getter-fn)
301315
result (cond
302316
(array? acc) (if (number? attr)
@@ -333,8 +347,8 @@
333347
(-contains-key? [this k] (not (nil? (lookup-entity this [k] true))))
334348
Object
335349
(get [this & attrs]
336-
(let [get-cb (:Entity/get-cb (meta this))
337-
v (lookup-entity this attrs true get-cb)]
350+
(let [{:keys [:Entity/get-cb ::after-lookup]} (meta this)
351+
v (lookup-entity this attrs true get-cb after-lookup)]
338352
(when get-cb (get-cb [this attrs v]))
339353
v)))
340354

src/homebase/react.cljs

Lines changed: 119 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
[goog.object]
77
[clojure.set]
88
[homebase.js :as hbjs]
9+
[homebase.cache :as hbc]
10+
[nano-id.core :refer [nano-id]]
911
[datascript.core :as d]
1012
[datascript.impl.entity :as de]
1113
[homebase.datalog-console :as datalog-console]))
1214

13-
14-
1515
(defn try-hook [hook-name f]
1616
(if hbjs/*debug*
1717
(f)
@@ -134,65 +134,83 @@
134134
initial-tx (goog.object/getValueByKeys props #js ["config" "initialData"])
135135
debug (goog.object/getValueByKeys props #js ["config" "debug"])
136136
_ (when debug (set! hbjs/*debug* debug))
137-
conn (d/create-conn (if schema
138-
(merge (hbjs/js->schema schema) base-schema)
139-
base-schema))]
140-
(datalog-console/init! {:conn conn})
141-
(when initial-tx (hbjs/transact! conn initial-tx))
142-
(react/createElement
143-
(goog.object/get homebase-context "Provider")
144-
#js {:value conn}
145-
(goog.object/get props "children"))))
137+
[initializing? setInitializing?] (react/useState true)
138+
db-conn (react/useMemo
139+
#(d/create-conn (if schema
140+
(merge (hbjs/js->schema schema) base-schema)
141+
base-schema))
142+
#js [])
143+
cache-conn (react/useMemo
144+
#(hbc/create-conn)
145+
#js [])]
146+
(react/useEffect
147+
(fn []
148+
(hbc/connect! cache-conn db-conn)
149+
(datalog-console/init! {:db-conn db-conn})
150+
(when initial-tx (hbjs/transact! db-conn initial-tx))
151+
(setInitializing? false)
152+
#(hbc/disconnect! db-conn))
153+
#js [])
154+
(if initializing?
155+
""
156+
(react/createElement
157+
(goog.object/get homebase-context "Provider")
158+
#js {:value #js {:db-conn db-conn :cache-conn cache-conn}}
159+
(goog.object/get props "children")))))
146160

147161
(defn ^:export useClient []
148-
(let [conn (react/useContext homebase-context)
162+
(let [{:strs [db-conn]} (js->clj (react/useContext homebase-context))
149163
key (react/useMemo rand #js [])
150164
client (react/useMemo
151165
(fn []
152-
#js {"dbToString" #(pr-str @conn)
153-
"dbFromString" #(do (reset! conn (cljs.reader/read-string %))
154-
(d/transact! conn [] ::silent))
155-
"dbToDatoms" #(datoms->js (d/datoms @conn :eavt))
156-
;; "dbToJSON" #(clj->js (datoms->json (d/datoms @conn :eavt)))
157-
"entity" (fn [lookup] (js/Promise.resolve (hbjs/entity conn lookup)))
158-
"query" (fn [query & args] (js/Promise.resolve (apply hbjs/q query conn args)))
159-
"transactSilently" (fn [tx] (try-hook "useClient" #(hbjs/transact! conn tx ::silent)))
160-
"addTransactListener" (fn [listener-fn] (d/listen! conn key #(when (not= ::silent (:tx-meta %))
166+
#js {"dbToString" #(pr-str @db-conn)
167+
"dbFromString" #(do (reset! db-conn (cljs.reader/read-string %))
168+
(d/transact! db-conn [] ::silent))
169+
"dbToDatoms" #(datoms->js (d/datoms @db-conn :eavt))
170+
;; "dbToJSON" #(clj->js (datoms->json (d/datoms @db-conn :eavt)))
171+
"entity" (fn [lookup] (js/Promise.resolve (hbjs/entity db-conn lookup)))
172+
"query" (fn [query & args] (js/Promise.resolve (apply hbjs/q query db-conn args)))
173+
"transactSilently" (fn [tx] (try-hook "useClient" #(hbjs/transact! db-conn tx ::silent)))
174+
"addTransactListener" (fn [listener-fn] (d/listen! db-conn key #(when (not= ::silent (:tx-meta %))
161175
(listener-fn (datoms->js (:tx-data %))))))
162-
"removeTransactListener" #(d/unlisten! conn key)})
176+
"removeTransactListener" #(d/unlisten! db-conn key)})
163177
#js [])]
164178
[client]))
165-
179+
166180
(defn ^:export useEntity [lookup]
167-
(let [conn (react/useContext homebase-context)
168-
cached-entities (react/useMemo #(atom {}) #js [])
169-
run-lookup (react/useCallback
170-
(fn run-lookup []
171-
(touch-entity-cache
172-
(try-hook "useEntity" #(hbjs/entity conn lookup))
173-
cached-entities))
174-
#js [lookup])
175-
[result setResult] (react/useState (run-lookup))
176-
listener (react/useCallback
177-
(fn entity-listener []
178-
(let [result (run-lookup)]
179-
(when (changed? #js [result] @cached-entities false)
180-
(setResult result))))
181-
#js [run-lookup])]
181+
(let [{:strs [db-conn cache-conn]} (js->clj (react/useContext homebase-context))
182+
hbjs-entity (try-hook "useEntity" #(hbjs/entity db-conn lookup))
183+
reactive-lookup-uid (react/useMemo #(nano-id) #js [])
184+
tracked-ea-pairs (react/useMemo #(atom #{}) #js [])
185+
;; hbr-entity (make-reactive-entity {:entity entity :setEntity setResult :tracked-ea-pairs tracked-ea-pairs :db-conn db-conn :cache-conn cache-conn :reactive-lookup-uid reactive-lookup-uid})
186+
[result setResult] (react/useState hbjs-entity)
187+
after-lookup (react/useCallback
188+
(fn after-lookup [{:keys [^de/Entity entity attr]}]
189+
(swap! tracked-ea-pairs conj [(:db/id entity) attr])
190+
(swap! cache-conn hbc/assoc-ea [(:db/id entity) attr] reactive-lookup-uid
191+
(fn change-handler []
192+
(let [entity (try-hook "useEntity" #(hbjs/entity db-conn lookup))
193+
_ (set! ^hbjs/Entity (.-_meta entity)
194+
{:homebase.js/after-lookup (:homebase.js/after-lookup (meta result))})]
195+
(setResult entity))))
196+
#_(js/console.log "after lookup" lookup (:db/id entity) attr @cache-conn))
197+
#js [result setResult lookup])
198+
_ (set! ^hbjs/Entity (.-_meta hbjs-entity)
199+
{:homebase.js/after-lookup after-lookup})]
182200
(react/useEffect
183-
(fn use-entity-effect []
184-
(let [key (rand)]
185-
(d/listen! conn key listener)
186-
#(d/unlisten! conn key)))
187-
#js [lookup])
201+
(fn []
202+
#(doseq [ea @tracked-ea-pairs]
203+
(swap! cache-conn hbc/dissoc-ea ea reactive-lookup-uid)
204+
#_(js/console.log "dissoc-ea" 10000 ea @cache-conn)))
205+
#js [])
188206
[result]))
189207

190208
(defn ^:export useQuery [query & args]
191-
(let [conn (react/useContext homebase-context)
209+
(let [{:strs [db-conn]} (js->clj (react/useContext homebase-context))
192210
cached-entities (react/useMemo #(atom {}) #js [])
193-
run-query (react/useCallback
211+
run-query (react/useCallback
194212
(fn run-query []
195-
(let [result (try-hook "useQuery" #(apply hbjs/q query conn args))]
213+
(let [result (try-hook "useQuery" #(apply hbjs/q query db-conn args))]
196214
(when (and (not= (count result) (count @cached-entities))
197215
(not= 0 (count result)))
198216
(reset! cached-entities {}))
@@ -208,14 +226,64 @@
208226
(react/useEffect
209227
(fn use-query-effect []
210228
(let [key (rand)]
211-
(d/listen! conn key listener)
212-
#(d/unlisten! conn key)))
229+
(d/listen! db-conn key listener)
230+
#(d/unlisten! db-conn key)))
213231
#js [query args])
214232
[result]))
233+
234+
;; (defn ^:export useEntity [lookup]
235+
;; (let [{:strs [db-conn]} (js->clj (react/useContext homebase-context))
236+
;; cached-entities (react/useMemo #(atom {}) #js [])
237+
;; run-lookup (react/useCallback
238+
;; (fn run-lookup []
239+
;; (touch-entity-cache
240+
;; (try-hook "useEntity" #(hbjs/entity db-conn lookup))
241+
;; cached-entities))
242+
;; #js [lookup])
243+
;; [result setResult] (react/useState (run-lookup))
244+
;; listener (react/useCallback
245+
;; (fn entity-listener []
246+
;; (let [result (run-lookup)]
247+
;; (when (changed? #js [result] @cached-entities false)
248+
;; (setResult result))))
249+
;; #js [run-lookup])]
250+
;; (react/useEffect
251+
;; (fn use-entity-effect []
252+
;; (let [key (rand)]
253+
;; (d/listen! db-conn key listener)
254+
;; #(d/unlisten! db-conn key)))
255+
;; #js [lookup])
256+
;; [result]))
257+
258+
;; (defn ^:export useQuery [query & args]
259+
;; (let [{:strs [db-conn]} (js->clj (react/useContext homebase-context))
260+
;; cached-entities (react/useMemo #(atom {}) #js [])
261+
;; run-query (react/useCallback
262+
;; (fn run-query []
263+
;; (let [result (try-hook "useQuery" #(apply hbjs/q query db-conn args))]
264+
;; (when (and (not= (count result) (count @cached-entities))
265+
;; (not= 0 (count result)))
266+
;; (reset! cached-entities {}))
267+
;; (.map result (fn [e] (touch-entity-cache e cached-entities)))))
268+
;; #js [query args])
269+
;; [result setResult] (react/useState (run-query))
270+
;; listener (react/useCallback
271+
;; (fn query-listener []
272+
;; (let [result (run-query)]
273+
;; (when (changed? result @cached-entities true)
274+
;; (setResult result))))
275+
;; #js [run-query])]
276+
;; (react/useEffect
277+
;; (fn use-query-effect []
278+
;; (let [key (rand)]
279+
;; (d/listen! db-conn key listener)
280+
;; #(d/unlisten! db-conn key)))
281+
;; #js [query args])
282+
;; [result]))
215283

216284
(defn ^:export useTransact []
217-
(let [conn (react/useContext homebase-context)
218-
transact (react/useCallback
219-
(fn transact [tx] (try-hook "useTransact" #(hbjs/transact! conn tx)))
285+
(let [{:strs [db-conn]} (js->clj (react/useContext homebase-context))
286+
transact (react/useCallback
287+
(fn transact [tx] (try-hook "useTransact" #(hbjs/transact! db-conn tx)))
220288
#js [])]
221289
[transact]))

src/homebase/reagent.cljs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@
6161
(defn make-reactive-entity [{:keys [^de/Entity entity r-entity tracked-ea-pairs db-conn cache-conn reactive-lookup-uid] :as args}]
6262
(let [top-level-entity-id (:db/id entity)
6363
e (Entity. entity {::after-lookup
64-
(fn [{:keys [entity attr]}]
64+
(fn after-lookup [{:keys [^de/Entity entity attr]}]
6565
(swap! tracked-ea-pairs conj [(:db/id entity) attr])
6666
(swap! cache-conn hbc/assoc-ea [(:db/id entity) attr] reactive-lookup-uid
67-
(fn []
67+
(fn change-handler []
6868
(reset! r-entity
6969
(make-reactive-entity
7070
(merge args {:entity (d/entity @db-conn top-level-entity-id)})))))

0 commit comments

Comments
 (0)
0