helix

lilactown 2021-10-25T15:37:37.027800Z

interesting - i tend to find the opposite 😄

lilactown 2021-10-25T15:39:11.029700Z

there's a certain inflection point where global state goes from being easier/simpler to showing its fangs. it's typically after developing the first few features and wanting to factor out some behavior into something that can be reused or shared

lilactown 2021-10-25T15:40:36.031100Z

one of the hardest parts of state management in an app is knowing what level to store it at. By defaulting to putting it in global state, I don't have to spend as much time thinking about that. it's also easy serialized, and to inspect and manipulate from a REPL. All good things!

lilactown 2021-10-25T15:43:28.033300Z

however, eventually I run into issues where I'd like to reuse and compose behaviors that I initially wrote using global state, and now I'm left with the decision to: 1. copy + paste the code I wrote before and find + replace names to new names, essentially replicating local scope using names in the global state 2. rewrite everything to use local state 3. other shenanigans??

👍 2
kennytilton 2021-10-27T10:36:45.057700Z

Agreed. Global is always super handy, but does not scale as the state grows in larger apps. One win of Matrix is that the state is at once globally accessible but at the same time provided with a natural scoping by the hierarchy in which state is arranged. This state hierarchy naturally follows the hierarchy of the application views, because views erect themselves from the state, then can access needed other state by searching hierarchically outwards from the view or view state immediately at hand. The RN version: https://github.com/kennytilton/matrix/tree/main/cljs/expo/matrixrn Needs doc. 😞 A bit more on the Web/DOM version (no React): https://github.com/kennytilton/mxtodomvc

kennytilton 2021-10-27T10:49:27.058100Z

The trick is making all objects in the Matrix tree aware of their parent objects, so we can search the entire global state, but do so navigating from immediate scope outwards. So a list view may have a dozen objects with delete buttons named :delete-button, but by default I find the one relevant to the local element. Fancier code lets me go beyond the default "nearest first" behavior.

kennytilton 2021-10-27T10:59:54.058300Z

ps. Yes, this global reach will scandalize the isolation devotees. But responsive U/Xes require global reach.

lilactown 2021-10-25T15:47:06.035600Z

I think your point about "temporary" state is what I find that the majority of state in my applications are. I basically have routing, data fetching & caching, theme, and then the rest is temporary state of whatever workflow is currently on the screen

lilactown 2021-10-25T15:47:25.036100Z

YMMV of course depending on your application. but that's why I default to local state first, and move the state up the tree until it's used by everything and I have perf issues and then move it to global 😛

lilactown 2021-10-25T15:48:18.036500Z

it's an easier refactor at that point too IME

Stefan 2021-10-25T19:55:41.038800Z

I’m greatful you are bringing in your perspective! I didn’t realise that I was having a narrow perspective, since re-use has not been an important aspect for me so far. Having said that, it has indeed given me headaches once or twice, so I recognise what you mean… Thank you!

lilactown 2021-10-25T19:56:13.039200Z

sure thing!

lilactown 2021-10-25T19:58:15.041600Z

our code practices are just as much a function of our use case and organizational structure as the technologies we use. I have often worked in organizations where I support many teams working on a shared codebase helping them evolve to scale to the number of devs they have. This is very different than a small, focused team maintaining a single project.

Stefan 2021-10-25T19:59:15.041900Z

Very true! 🙂

Stefan 2021-10-25T06:41:33.027300Z

That’s good advice, @lilactown. I find that the programming model using global state tends to make my apps simpler, easier to understand and reason about. So while you’re of course right that we have to consider what we want to use it for, for that reason alone I lean towards using global state “by default” in new apps for state that is not “temporary” (e.g. form state while filling out the form).