"a little nervous about the JVM" 😄
I'm starting to build an app with cljfx, I was a little nervous too at the beginning (being used to the web for UIs) but the more I'm reading the docs, examples and the code, the more I like it.
Escaping from clojurescript is quite nice, don't be reluctant to use macros or clojureJVM's spécific constructs is quite liberating.
One thing that I don't really get is how I'm supposed to use contexts. As far as I understand for now, every view function can receive the whole context as part of the description, and we can use fx/sub-val
to build the data that our view is needing, it is nice, but I'm wondering if it would be even nicer to decouple those to things.
Thinking about this I was wondering if it would be a decent practice to create a sub-context like this:
(-> whole-context (fx/sub-val f) fx/create-context)
And passing it into the view function instead of the whole app context.
Doing this seems to allow to be able to plug views into different contexts without modifying the view function itself.
One nice thing I think would be to be able to define UI components that are context agnostics by letting the user specifying how the component plugs into the host app context.
Some analog reflexions could be done about events and effects I think.
One other thing that intrigues me is coeffects in the example 18. In re-frame, I believe, coeffects are attached to particular events at registration time, here coeffects seems to be global (computed for every event).
Of course, tackling those concerns is possible with the current implementation of cljfx which is surprisingly simple and flexible ! But I'm curious to know what you think of those ideas.
Have a nice week end.
The purpose of contexts is to pass the whole state to every component, if you want decoupling you can pass the minimum amount of data as arguments. Contexts = easy yet complex, arguments = simple and sometimes easy, sometimes hard.
I did contexts because I had a lot of positive experience with re-frame that uses similar model. I made all that stuff (contexts, effects, co-effects) optional because I don't have a strong opinion that this is a one true way to do UI app development
I built Reveal on cljfx and it does not use contexts, effects and co-effects, instead the whole app state is flowing through arguments, and event handling is done differently: every event handler has to return a function that will be used to swap!
the current app state. I think this approach is better than deref in co-effect + reset in effect since it's atomic.
Although, one thing I did to make stuff easy in Reveal is I built a horrible hack to support "local mutable state" that can read and write in a state map using a special lifecycle. Horrible, but very useful.
Thanks for the clarification, this idea of returning a swap function from the event-handler is interesting ! I think that for handling global mutable state it is nicer than deref+reset indead. But maybe for other "effects" like database read-write, re-frame approach would be preferable.
I neither have a strong opinion on UI app dev. I like re-frame too, but sometimes I find it a little overkill.
I'm curious about what yields you to need local mutable state in Reveal.
Other "effects" are executed directly in event handlers :P