I'm curious if you've ever looked at optics-based systems for component coupling?
Personally I think that the entire top-down state tree is a bad idea, but I'm willing to be convinced. I'd much prefer a modeling like the actor approach.
Keeping all external state in a db like abstraction, and having any component, regardless of view tree depth, be able to query against it for data that it needs, and have it update when that data changes, is the way to go, and it's the future.
Applications developed this way are very easy to change and update. Deleting a completely self contained component, not having to update the parent by removing the wiring of the data, is a blessing.
A lens is an object that has both read and write access to a property of an object (or to a path into a tree of nested objects).
Rather than passing parts of the model to the children (as you'd do with React props), you pass lenses into said parts.
It enables child components to read/write to the global store without knowing its structure. As long as it receives an appropriate (set of) lens(es) it is happy.
So, for example, if you have a list of strings, rather than passing the nth string to the nth component, you'd pass a lens to the nth string. The component can then not only read but also write to its slot.
Lenses can also be composed, so you can create them on the go as you'd pass sub-props to grand-children.
These libs are strongly influenced by the FP world. The underlying data structures are immutable, writing to a lens creates a new version of the store (as efficiently as possible, by recycling intact objects).
So basically, it's like using dependency injection, and what you're injecting are higher order functions for the getters and setters for whatever properties you need. Is that right?
Do they need to be functions? Because this seems a lot like handling [:a :keyword :vector :for :navigating :trees] in Clojure and passing it to either update-in or get-in functions, which is a pattern ubiquitous in re-frame, but not sure is can be called a lens).
What you're saying sounds similar. But my question and your post are both missing the "composition" aspect. Somehow lenses are composable, and I guess to grok that we'd need to look deeper.
However, recently I discovered Halogen [0]. It is very similar to Elm Architecture, however, every component has its own _internal_ state, so you do not have to thread all state changes to the top-level component. It does this by existentially quantifying over the State [1].
Halogen is written in Purescript, which is a transpiler for javascript (yes transpiler, not compiler). Which means you basically get javascript semantics with a haskell typesystem + very good interop with JS, and no runtime system. The code purescript generates is actually readable. [2]
Thank you for being a force for sanity in the universe. "Transpiler" is a distinction without a difference to add yet more jargon to our already cryptic profession.
In this case the optics are used as a way to select state in the coupling construct. You don't use them to read values out of the form, you use them to explain to the components how to pull or update their state out of the shared construction.
Personally I think that the entire top-down state tree is a bad idea, but I'm willing to be convinced. I'd much prefer a modeling like the actor approach.