Ah, so glad to see youβre speaking @dustingetz!
How do you guys go about state management? I've experimented a bit with a global state atom and a bit with having state all around the component tree, but I'm not really sure what's better π
https://electric.hyperfiddle.net/tutorial/todomvc has a traditional binding, the root fn binds db, transact fn etc. spy or Spy is not an actual thing, you can use prn or w/e suits your debugging needs
https://electric.hyperfiddle.net/tutorial/todomvc_composed especially
there's no 1 way to do this, depends on your use case. Personally I try to match the usage scope.
β’ a modal's open state has scope local to the modal (usually others don't read/write to it) => let-bound, passed as argument where needed
β’ a db connection has global scope (any component might need it) => binding at the root of the application so we don't need to pass it into the depths
Then there's questions of persistence & browser behavior
β’ which tab you're on in an SPA - probably want to read/write in the URL so it opens on reload
β’ user session - store in a db
yes, i think about this in terms of encapsulation hierarchies
I dont think "global state atom" is intellectually honest, when you consider the client/server hollistically, the client singleton is no longer "global", it is just a level in a hierarchy. And working with Electric long enough starts to put pressure on the "client singleton is global" worldview
What I really like about the single client atom approach is that it makes the whole state a value, so I can take a look at the whole of it and do others things like having an atom watch print a diff every time it changes. It ends up becoming cumbersome if I'm dogmatic about it though π
I have found that using binding in the same fashion as https://react.dev/learn/passing-data-deeply-with-context works pretty well as a solution to props drilling
context/binding can be global if you put it at the root level but doesn't have to, so it's more flexible
yes, electric binding is react context and comes with the lifecycle methods for free
electric binding is therefore also comparable to Stuart Sierra Component pattern
@post972 consider e.g. (println (dom/input (dom/On "input" (fn [e] (-> e .-target .-value)) ""))). No atom. And yet it is stateful. Do we really need to put this in global state?
Sometimes you do, sometimes you don't
@post972 that approach requires a (swap! !global assoc-in [:foo :bar] my-value) in every place you wish to track state. If you're touching those places anyway you can track the changes granularly by replacing those lines with (spy [:foo :bar] my-value), spy being whatever you want it to be. It could even be an electric dynamic you are binding at the root and bind it to something in dev and noop in prod. Or it could be Spy and be an electric fn that might send the value to the server for w/e reason
Is there an example using binding or Spy?
The browser is so full of state all over the place that the βone stateβ methodology becomes inaccurate almost immediately. For example, if you use a router, you also have state in at least one more place (the address bar). We used to do the single atom approach way back. I donβt remember if we felt that it was actively detrimental in the end, but it was at least no silver bullet, and not obviously better than slicing the state in different ways.