This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-08-08
Channels
- # announcements (1)
- # babashka (39)
- # beginners (44)
- # clj-kondo (10)
- # cljdoc (24)
- # clojure (49)
- # clojure-austin (2)
- # clojure-berlin (6)
- # clojure-europe (13)
- # clojure-nl (1)
- # clojure-norway (5)
- # clojure-uk (1)
- # core-async (11)
- # cursive (7)
- # datahike (3)
- # datalevin (2)
- # fulcro (1)
- # hyperfiddle (40)
- # jobs (12)
- # juxt (5)
- # lsp (9)
- # nyc (1)
- # off-topic (27)
- # re-frame (7)
- # releases (3)
- # shadow-cljs (9)
- # timbre (6)
- # xtdb (2)
- # yamlscript (1)
Would a e/binding
macro be useful that creates bindings for both client and server scope be useful? Something like this:
(defmacro sync-binding
"Does binding in both server and client scope. Make sure to explicitly specify the scope in bindings (e.g. e/client or e/server). Body is evaluated in client scope."
;; possibly improve by preserving the caller's scope
{:style/indent 1}
[bindings & body]
`(e/server
(binding ~bindings
(e/client
(binding ~bindings
~@body)))))
One nice thing with Electric is since lexical variables are automatically transferred, I don't have to nitpicky about where the variable is coming from, and maybe we can preserve those semantics for binding.maybe, unclear – i was playing with something like this too (focused on pyramid flattening), see https://github.com/hyperfiddle/electric/blob/2dc4f9a1b555df343e646452e3045da04a84344a/src/contrib/clojurex.cljc#L14-L20
requirements seem to be:
• no pyramids (allow causal dependencies in bindings)
• e/client and e/server at any point, strategy for dealing with it
• support both let
and binding
(perhaps based on presence of a var? perhaps too error prone)
you will eventually hit some complexities about clojure bindings vs electric bindings that is on our backlog to take a fresh look at
also be aware of the issue "no electric binding unification yet" – when you e/def, you get both clojurescript and clojure electric def – there are two defs – which is why you need to be super explicit when you read an electric binding (as opposed to reading let
bindings which are always bound to a single site) . This also is on our backlog to fix this fall
I’ve been wanting something like this. I have a “boot” section of the app where server and client blocks are taking turns throwing stuff at each other so that a bag of e/def
s end up synchonizing.
It got trickier when some bindings became inputs to other bindings. I briefly thought of throwing Ubergraph at it to resolve dependency order behind a macro.
@U06B8J0AJ bindx
above should help with the dependency issue, however I never got it working in clojurescript and have no idea currently why it doesn't work in clojurescript
note the funcool/cats alet
macro includes topo sorting capability over alet bindings, you could probably copy paste it subject to their license
In the following code, is an infinite cycle expected when pressing the button? It's a bit weird to me since I would expect the e/fn
to be executed only once. Perhaps this is because of the function-component duality.
(defonce !conn (d/create-conn {}))
(e/def some-value (e/server (:value (d/entity (e/watch !conn) 1000))))
(e/defn App []
(e/client
(e/server (d/transact! !conn [{:db/id 1000 :value 10}]))
(ui/button
(e/fn []
(e/server
(println "button pressed") ; prints forever
(d/transact! !conn [{:db/id 1000 :value (+ some-value 1)}])))
(dom/text "[Increase Value by 1]"))
(dom/text some-value)))
For this particular case, the fix is easy (just change some-value to (:value (d/entity @!conn) 1000)
, but for my actual use case, I have several reactively connected e/def
that are used within e/fn
. It would be really handy to be able to write like functions like this because otherwise, I wouldn't be able to reuse any logic within these reactive atoms.
this is a more complicated example of
(let [!x (atom 0), x (e/watch !x)]
(reset! !x (inc x)))
. reset!
will re-run if any of its arguments change, so this is a cycle.
The solution for atoms is to use the more typical (swap! !x inc)
.
The same solution in the database world would be transaction functions I guess.if you really wish for the cycle to exist today you can break the cycle with e/snapshot
. The tightest fix would be (inc (e/snapshot some-value))
Oh, interesting. That's perfect for my use case. Why doesn't e/snapshot
return some-value at the point of when App was mounted?
Yeah, I would expect (e/snapshot some-value)
to always return 10, since it was frozen at that initial value.
I see. ui/button
mounts the e/fn
when you click it and unmounts it when the e/fn
returns a non-Pending value. That means the code inside it is mounted anew on each click, thereby running a new snapshot. Does that make sense?
ooh didn't know about e/snapshot
we don't promote it too much since we're hoping it won't be needed in the next iteration. But for now it's a reasonable weapon in one's arsenal
Anyone have an Electric + Reitit routing example lying around?
If you search my messages I should posted couple of times, let me know if you can't find it.
Thanks! What do I search for? Can’t seem to find in channel for term “reitit”
Found this cljs mention but looking for server-side: https://clojurians.slack.com/archives/C7Q9GSHFV/p1687788322928669?thread_ts=1687708239.825519&channel=C7Q9GSHFV&message_ts=1687788322.928669
Thanks, @U5H4U2HEH !
@U5H4U2HEH does "FIXME: Authenticate WS Connection" mean that WS connections are allowed even without auth? I guess fine as long as you check for session in Electric?
> I guess fine as long as you check for session in Electric? That is my assumption also, a while back I also confirmed this with @U09K620SG. That said I would feel better if I can figure out how to check for authentication when ws connection opens.
authentication is intended to be done in userland so you can render a login page with electric
see demo-chat-extended
Thats pretty much how I handle it but ws connection still can be initiated when user is not logged in so I check the session in electric to make sure user is authorized. This is not related to electric but if anyone knows how to configure jetty so it only allows authorized ws connections I'll be great full.
@U5H4U2HEH wrap-content-type
middleware seems to be overriding Content-Type to application/octet-stream
which prompts browser to initiate download prompts. Surprising because wrap-content-type should only override if Content-Type
header is not present.
Do you have a more complete sample, please?
For future Reitit searches, most up-to-date is here via @U050CJFRU: https://clojurians.slack.com/archives/C7Q9GSHFV/p1687788322928669?thread_ts=1687708239.825519&cid=C7Q9GSHFV
How do you scroll to bottom when you mount? Since dom/on "mount"
doesn't exist, I am trying the following:
(dom/div
(dom/props {:class (tw "overflow-auto max-h-96")})
(set! (.-scrollTop dom/node)
(.-scrollHeight dom/node))
;; rest...
)
It doesn't quite work, and not sure where to proceed from here.save a reference to dom/node and then run your side effect at the deepest part of the view, you can use a macro to make the syntax better
deepest = causally last child leaf of the view
off the top of my head