This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-10-19
Channels
- # announcements (5)
- # babashka (13)
- # beginners (62)
- # calva (46)
- # cider (24)
- # clj-kondo (4)
- # clojure (12)
- # clojure-europe (21)
- # clojure-hungary (1)
- # clojure-nl (1)
- # clojure-norway (18)
- # clojure-uk (6)
- # clojuredesign-podcast (4)
- # clojurescript (9)
- # conjure (1)
- # core-async (5)
- # datomic (3)
- # emacs (1)
- # holy-lambda (14)
- # hyperfiddle (36)
- # jobs-discuss (3)
- # joyride (7)
- # lsp (35)
- # om-next (1)
- # pedestal (11)
- # podcasts-discuss (1)
- # practicalli (2)
- # releases (3)
- # sci (17)
- # shadow-cljs (5)
- # testing (4)
- # tools-deps (10)
- # vim (2)
- # xtdb (5)
I'm recursively rendering reply/comment components and getting StackOverflows, I wonder if there is a way to do it without poppin the stack. Code in thread
(e/defn ItemView []
(e/server
(let [e (xt/entity db current-item-xt-id)
xt-id (:xt/id e)
item-xt-id xt-id
link (:item/link e)
item-id (:item/id e)
author (:item/minted-by e)
minted-at (:item/minted-at e)]
(e/client
(dom/div (dom/props {:class "itemview fc"})
(dom/div (dom/props {:class "fi"})
(dom/text link))
(dom/div (dom/props {:class "fi"})
(dom/text author))
(dom/div (dom/props {:class "fi"})
(dom/text item-id))
(dom/div (dom/props {:class "fi"})
(dom/text minted-at))
(when (not= current-item-xt-id "")
(dom/div (dom/props {:class "reply-input fi"})
(ReplyCreate. xt-id xt-id)))
(dom/div (dom/props {:class "replies fr"})
(e/server (e/for-by :xt/id [{:keys [xt/id]} (e/offload #(reply-with-descendant-records db item-xt-id item-xt-id))] (ItemNestedReplies. id)))))))))
(e/defn ItemNestedReplies [xt-id]
(e/server
(let [;i (xt/entity db current-item-xt-id)
r (xt/entity db xt-id)
text (:reply/text r)
author (:reply/minted-by r)
minted-at (:reply/minted-at r)
item-xt-id (:reply/item-xt-id r)
upvotes (:reply/upvotes r)
parent (:reply/parent-xt-id r)]
(e/client
(dom/div (dom/props {:class "itemreplies fc"})
(dom/div (dom/props {:class "fc"})
(dom/div (dom/props {:class "fi"})
(dom/text text))
(dom/div (dom/props {:class "fi"})
(dom/text "xt-id: " xt-id))
(dom/div (dom/props {:class "fi"})
(dom/text "item: " item-xt-id))
(dom/div (dom/props {:class "fi"})
(dom/text "parent: " parent))
(dom/div (dom/props {:class "fi"})
(dom/text author))
(dom/div (dom/props {:class "fi"})
(dom/text upvotes))
(dom/div (dom/props {:class "fi"})
(dom/text minted-at))
(dom/div (dom/props {:class "fi"})
(NestedReplyCreate. current-item-xt-id xt-id))
(dom/div (dom/props {:class "fi"})
(dom/div (dom/props {:class "replies fc"})
(e/server (e/for-by :xt/id [{:keys [xt/id]} (e/offload #(reply-with-descendant-records db item-xt-id xt-id))] (e/client (dom/div (dom/text id))))))) ;(ItemNestedReplies. id)))))
(dom/div (dom/props {:class "fi"})
(ui/button (e/fn [] (e/server (e/discard (xt/submit-tx !xtdb [[:xtdb.api/delete xt-id]])))) (dom/text "✗")))))))))
;;item == newsitem
;;parent == parent
(e/defn ReplyCreate [item-xt-id parent-xt-id] (e/client (InputSubmit. "reply" (e/fn [v] (e/server (e/discard (e/offload #(xt/submit-tx !xtdb
[[:xtdb.api/put
{:xt/id (random-uuid)
:reply/text v
:reply/id (nid)
:reply/minted-by online-user
:reply/upvotes 0
:reply/item-xt-id item-xt-id
:reply/parent-xt-id parent-xt-id
:reply/minted-at (System/currentTimeMillis)}]]))))))))
(e/defn NestedReplyCreate [item-xt-id parent-xt-id] (e/client (when (and item-xt-id parent-xt-id) (InputSubmit. "nested reply" (e/fn [v] (e/server (e/discard (e/offload #(xt/submit-tx !xtdb
[[:xtdb.api/put
{:xt/id (random-uuid)
:reply/text v
:reply/id (nid)
:reply/minted-by online-user
:reply/upvotes 0
:reply/item-xt-id item-xt-id
:reply/parent-xt-id parent-xt-id
:reply/minted-at (System/currentTimeMillis)}]])))))))))
#?(:clj
(defn reply-with-descendant-records [db item-xt-id parent-xt-id]
(->> (xt/q db '{:find [(pull ?r [:xt/id :reply/text :reply/item-xt-id :reply/parent-xt-id :reply/upvotes])]
:where [[?r :reply/item-xt-id item-xt-id]
[?r :reply/parent-xt-id parent-xt-id]]
:in [item-xt-id parent-xt-id]} item-xt-id parent-xt-id)
(map first)
vec)))
You can see the commented out end of the line (e/server (e/for-by :xt/id [{:keys [xt/id]} (e/offload #(reply-with-descendant-records db item-xt-id xt-id))] (e/client (dom/div (dom/text id))))))) ;(ItemNestedReplies. id)))))
And the reason this comment is there is because if I delete from (e/client...)
and uncomment that, I get a stackOverflow.
I think i need a way to "bottom out" or "zero out" on the recursive query :thinking_face:
I added another component that does not recurse / recur and it "bottoms out" on 1 nested comment. I could artificially mint several more to add a semblance of depth / nesting. I thought I could do the same with a depth
and max-depth
Please post code snippets longer than 3 lines as a slack snippet (Ctrl+Shift+Enter or start typing /snippet) or a a github gist or repo
we've landed fixes on code size and nesting on the main branch, could you retry with the latest git sha?
how deep is the recursion? (in addition to what Peter asked)
you need a base case, an if statement guarding the recur point
def factorial(n):
if n > 0:
return n * factorial(n - 1)
else: # base case, no recur
return 1
Okay that makes sense. I attempted "let the replies be (e/offload...) if replies render otherwise no render, but that also not working ...
I think (e/for-by [] ...)
will be the base case here, when the query returns an empty resultset
oh i must have misread
So in theory, i can check if replies
has any entries, and render or not. I think I understand the concept but I am still running into StackOverflows.
If I print replies to console I see []
or [...]
results ...
I must be doing something very naively
please include the exception you're seeing here in the chat. Have you tried latest electric sha?
😅 some stuff broke but unclear why ... investigating. some of my components stopped rendering
My online list of users, the chat, and some real-time components nested in there were not rendering at all with the bump so I rolled back to v2-alpha-349-ge9996713
you are right that the query returns an empty result []
... not sure how i can prevent rendering once I know that, I think I am missing something fundamental about execution sequence / assignment sequence
Okay, I expected that to be true, but I encounter stack overflows, so :man-shrugging: tap out for now lol 4 levels deep via manual component creation (aka 4 new components) is fine for now and the forseeable future. if i can figure out "infinite replies" on comments that would be awesome, but it overflows so, gotta focus on tubs i can manage the water level in 😅
was trying the ic
branch for fun and though incremental is still broken, it seems to be a lot faster (13s->8.5s) with no other changes
oh, I thought boot-client
would have been the entrypoint. but just the same old boot
seems much faster too
today the client boots and sends electric IR over to the server in the first websocket message. The server interprets the IR. With IC we split the code and the both peers run their compiled part of the program
Does anyone have a workflow they can share for reusable UI components (like the React crowd often leans toward)? And as a side question, and less importantly, can anyone share any inspiring app examples, UI'wise? I understand the magic of Electric is not focused on the UI, but the graphical interface is a practicality I have to deal with, alas.
Reusable ui components? I think all components should be reusable if possible, a component for each view is optional, and a component for each item you're going to iterate over... My workflow is basically: 1. get a working example repo and merge/mold them together if I need 2 features 2. create InputSubmits. for each of the data thingies I need, like posts, or users, or whatever 3. Generate some data via text input and have them show to the ui immediately 4. basically make sure i have this immediate database-like view on all the data before i start drawing up more comlpex components 5. then, start working on the app in terms of interface, 6. in electric land, lines of code currently affets compilation time so... fewer components is better.! 😅