This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-09-26
Channels
- # aleph (3)
- # announcements (6)
- # babashka (14)
- # beginners (8)
- # biff (16)
- # calva (4)
- # cider (7)
- # clj-kondo (8)
- # cljs-dev (26)
- # clojure (65)
- # clojure-austin (2)
- # clojure-brasil (1)
- # clojure-europe (35)
- # clojure-nl (4)
- # clojure-norway (45)
- # clojure-portugal (1)
- # clojure-uk (9)
- # clr (5)
- # community-development (6)
- # conjure (1)
- # cursive (3)
- # events (8)
- # fulcro (1)
- # honeysql (19)
- # hyperfiddle (31)
- # introduce-yourself (1)
- # lsp (7)
- # matcher-combinators (10)
- # off-topic (17)
- # practicalli (1)
- # ring (30)
- # shadow-cljs (6)
- # testing (2)
from a cursory look, runes (new in svelte 5) feel like incidental complexity/artifacts
Given how electric manages updates. Are there already best practices how to manage purely frontend state with electric? I can think of 3 alternatives. 1. one global atom. Having an e/watch in any clientside component. pro: simple to implement, con: triggers some reevaluating in every component on state change 2. split state into many atoms. Pro: absolute minimum recalcultion on state changes. Con: clutters state 3. fulcro like global atom. state is injected as fn arg into component. Pro: good reasoning about state. con: “props drilling react like problems” Personally, I would go with method 1. How would you do it with electric?
I just realized that I can do another 4th alternative.
(def !state (atom {}))
(e/def state (e/watch !state))
(e/def topic1 (:topic1 state))
(e/def topic2 (:topic1 state))
(e/defn MyComponent []
(dom/div (dom/text topic2)))
This has the benefit of having state in 1 place. No props drilling is needed in the component. Nested components are decoupled. State could be even a normalized db like in fulcro with denormalization for components. This 4th alternative seems the right way to goI wrote my own, first with odoyle+asami for reactive inline datalog, now in an EQL style heavily inspired by fulcro. it works well though I need to rewrite it yet again on top of differential electric soon. Note that your option 4. is basically how react renders but even less efficient since you don't get to skip subtree diffs
also, don't underestimate the importance of transactions. i've ran into some very confusing stacktraces in electric already because of badly timed state updates
> since you don't get to skip subtree diffs
What do you mean by skipping subtree diffs? In option 4 (dom/text topic2)
will re-run only if topic2
changes. If the !state
atom updates but (:topic2 state)
returns the same value (same via clojure.core/=
) downstream dependencies will skip all work
it needs to run every diff (checking if (:topicN state)
returns the same value) every time !state
updates since he doesn't want to do prop drilling
with react you diff mounted components, and if the parent doesn't render no work is done for its children
basically you want to diff as far upstream as possible. that's why react's low level built-in diffing (vdom<->dom) isn't that impressive
checking if (:topic2 state)
is =
when there have been no changes on that branch succeeds at pointer comparison, I wouldn't worry about that cost
in our ideal world view diffing is accidental complexity introduced at the edges of your system where you have to interoperate with third parties that send you collections. e/for
diffs and in next electric version everything will be differential
it is very cheap and react (in the happy path) is plenty fast, though not quite free, so you do get something of a "death by a thousand cuts" effect. definitely not relevant for most apps
e.g. if rama can send fine grained updates (CUD) we should be able to integrate that seamlessly and achieve "perfect" performance
diffing as a threshold problem makes sense, it's like a breakdown of trust/communication so you have to verify first which has a cost
to address the q of state management: I hesitate to prescribe solutions here yet, we are still learning - electric is different, and differential electric (coming this year) is even more different and extremely powerful
UI5, the optimistic update forms library, has a new flow-based pure functional state management approach (no callbacks). it is blocked on differential electric
my instinct is that callback-free flow composition is the path forward for electric state management but in the meantime we are stuck with change callbacks
also since the UI5 workstream is blocked, this is all just a hypothesis until we see it working
Is it possible to do e/server
or e/client
from a react or reagent component?
I am trying to make a svg playground UI which has codemirror, prosemirror and a few other type of nodes in the playground. I currently have this in working state using re-frame and reagent but I want to move over to electric.
no, those special forms are only valid inside the electric macro contexts
the best you can do is use electric to pre-fetch the data and pass it into the foreign context
or implement some sort of subscription machinery form the foreign context to send an event back into the electric context to signal a request for more data
oh ok thanks for the quick reply Dustin. I really like working with electric, I find it much more intuitive to use than reagent and any other framework. I think I should implement the svg playground in electric itself not sure the complexity of doing so.
can i see a screenshot of what you have?
This is screenshot I have from the working code in reagent, the blue part is codemirror editor when we run the code we get output in the white area. We can then pass this result to another such node. The playground in which these nodes exists is build on reactflow. Sorry I could not share a better screenshot because I don't have a running build as of now.
bridging react is a common question, here are some links • https://github.com/hyperfiddle/electric/blob/c910935c7068ee5af457a64157a6e12923b8393e/src-docs/user/demo_reagent_interop.cljc • https://github.com/KevinTung/electric-testing-1/blob/main/src/app/todo_list.cljc (@U03RQQ2L8LE’s repo, I helped) There are rough edges we can help clean up. If you hit a specific scenario where you get stuck I'll be glad to help
Here are some context: https://clojurians.slack.com/archives/C7Q9GSHFV/p1693321123284739 https://clojurians.slack.com/archives/C7Q9GSHFV/p1693840471256199 https://clojurians.slack.com/archives/C7Q9GSHFV/p1695109763946729 I ultimately used a normal event atom to store and trigger update. It functioned well .
Thanks @U09FL65DK and @U03RQQ2L8LE! I will try to use this and ask if I hit some blocker.