wd guys I'm seeing a significant performance boost with the new lockless impl., with no regressions so far.
General Electric performance question: given a nested tree of Electric component nodes and a global atom containing expansion data (e.g. (let [expand? (boolean (get (e/watch !state) node-id))] ...), is it faster to (e/watch !state) the state in the top-level / root component and pass the value down the tree as a component argument, or to (e/watch !state) in each node?
one should e/watch an atom only once, multiple watches can cause glitches
if there's a perf diff idk
oh dear, I didn't know that.
I have e/watch all over the place, and I can confirm the state glitches.
Resolved by e/watch in root and passing down as arg.
can you safely e/watch the same atom multiple times in distinct, non-nested, components?
it is always safe but glitch-prone. I'd either pass it to all components or bind in a binding
Perf. difference between passing down vs dynamic binding?
> Perf. difference between passing down vs dynamic binding?
argument passing is implemented with dynamic bindings, there should be no difference
the lockfree release does contain an optimization which is unrelated to the removal of the locks
https://github.com/henryw374/time-literals for data readers like #time/date "2025-10-29" works in dev but fails in uberjar production compilation:
165 | (e/defn MyComponent [data {:keys [width height
-------^------------------------------------------------------------------------
Encountered error when macroexpanding hyperfiddle.electric3/defn.
IllegalStateException: Attempting to call unbound fn: #'time-literals.data-readers/date
clojure.lang.Var$Unbound.throwArity (Var.java:47)
despite #time/date not used in that component (only in caller).
Is there a trick to get custom data readers working with Electric v3, or is this not an Electric issue?
btw. I don't think this is new i.e. not related to lockless impl.does the literal work if you put it in clojure defn? Don't put a reader conditional around that defn. Electric compiles on clj and cljs so this will test if both are correctly set up. For the same reason #js doesn't work in electric code. If the reader works in a defn then it's an electric bug
by the last defn, do you e/defn or clj defn? #time/date works in an e/defn in dev build
if it works in cc/defn it's an electric bug
i'm trying to troubleshoot a simple e/fn handler
(e/defn InvokeChild [on-trigger]
(dom/div
(dom/button
(dom/text "press me")
(let [[ack err] (e/Token (dom/On "click" identity nil))]
(when ack
(println "CLIENT")
(if (= (on-trigger (rand-int 10)) ::handled)
(ack)
(ack "error")))))))
(e/defn Demo []
(dom/div
(InvokeChild
(e/fn [v]
(e/client (println "CLIENT HANDLER" v))
(e/server (println "SERVER HANDLER" v)
::handled)))))
when i click the button, i see CLIENT but not CLIENT HANDLER or SERVER HANDLER in the logs. what gives?The call convention for electric functions is, that these must begin with a capital letter or explicitly called as an electric function. In your example electric tries to call on-trigger as a normal clojure function. Change on-trigger to On-trigger .