Fork me on GitHub
#helix
<
2021-07-25
>
kennytilton15:07:49

So I am making satisfactory baby steps with Matrix+Helix+React (not yet native, just warming up for that). I have indeed worked out how to use the use-state hook to trigger renders when Matrix sees the need. Yay. But to do this I am doing a top-level DEFNC and I am hoping to come up with in-line equivalent. Right now I have this adding a test "div" : (mxr/make-rx :feed (cF (str "Fed Content " (mget (mxu! me :counter42) :counter))) :rendering (cFonce ($ H1Test {:me me}))) "feed" will get picked up from "me" in the H1Test rendering. I tried passing it as a prop but that broke things. That is in a tree of rendering. Works great, but relies on a top-level DEFNC: (defnc H1Test [{:keys [me]}] (let [[_ set-state] (hooks/use-state 0)] (mxr/set-state-record me set-state) ;; <-- used by Matrix on-change handler to trigger re-render (d/h1 (str "h1 test " (mget me :feed))))) Now one of the charms of Matrix is that I can build a solid wodge of UI without having to stop to carve out a named top-level widget. This works because in Matrix we are at run-time defining interesting "anonymous" if you will components, each which enjoys its own lifecycle without triggering those of others around it. The alternative is to slow down coding, just as "C" forced us to code a sort function top-level so we could take its address and pass it to sort. So I am hoping for: (mxr/make-rx :feed (cF (str "Fed Content " (fmv :my-counter :counter))) ;; <--state from a diff widget :rendering (cFonce ($ (lambdac [{:keys [me]}] (let [[_ set-state] (hooks/use-state 0)] (mxr/set-state-record me set-state) ;; <-- used by Matrix on-change handler to trigger re-render (d/h1 (str "h1test " (mget me :feed))))) {:me me}))) Once we have that, 90% of that can be hidden by sufficiently clever macrology. (mxr {:feed (cF (str "Fed Content " (fmv :my-counter :counter)))} (with-props [feed] (d/h1 (str "h1test " feed))) I will dive into Helix to see how to do lambdac, but I thought I would ask here in case it is an easy one I have missed so far. Thx!

lilactown17:07:15

why does make-rx take a React element?

kennytilton23:07:16

Matrix controls all, including the structure of an interface. ie, the children of a component are also a reactive property. And there is anyway a problem: Matrix dependencies are detected at run time, not compile time. Even MatrixCLJS had a problem because of lazy evaluation: a critical dynamic depender var was no longer bound by the time the dependent code ran. Had to add a doall. I have seen the same with Helix/React already because React runs view functions when it feels like it. It is working out better to let Matrix drive React. So far. Just looked at fnc. "anonymous functional component"? I was going to use those words! :rolling_on_the_floor_laughing:

lilactown17:07:28

I think you're going to struggle with having matrix try and take over and manage the entire rendering of the app over React

lilactown17:07:51

what I would suggest is inverting that control: use React naturally where you compose your application with components that return elements. and then in the body of a component, you can reference a matrix reactive value which will set up the on-change handlers

lilactown17:07:59

i.e.

(defnc h1-test
  []
  (let [me (mxr/use-rx
             :feed (cF (str "Fed Content " (fmv :my-counter :counter))]
    (d/h1 (str "h1 test " (mget me :feed)))))

(defnc app-root
  []
  ($ h1-test))

(rdom/render ($ app-root) (js/document.getElementById "app"))

lilactown17:07:05

your job then would be to provide the use-rx hook/macro as a library which handles subscribing to the matrix value created in the body of the component

lilactown17:07:38

that being said, there is a fnc macro in current master of helix. I haven't tested it in production yet but you're welcome to give it a whirl!

kennytilton22:07:46

Aha! I did have my eye on fnc*! I will give fnc a try. Are there any working examples? I am useless without working examples. Thanks for the h1-test suggestion, but it has the same problem: it is not inline. When I am writing Matrix code describing an interface, I just type madly away defining the structure in one big blob. As with programming in general, if the blob gets too big I break a chunk out, not because it will be reusable, just to make the source manageable. Otherwise, I have the whole interface right in front of me for sculpting, or large wodges of it. This is one of the keys to rapid development, in my experience. Tools like re-frame want us forever to be exploding our concepts into scattered lists of subs, events, and views we have to mentally (and textually!) juggle while coding. I think for certain mind sets that decomposition provides a warm fuzzy, but all I experience is the mental juggling and endless text searches,. "I think you're going to struggle with having matrix try and take over and manage the entire rendering of the app over React" I was starting to think the same thing after looking at Helix and Reagent internals, and after reading the nonsense from React engineers about "we want to be in control". There's a road to Hell. But I have done similar glue to drive Tk/Tcl, OpenGL, and Qooxdoo and driving React is starting to feel the same, and doable thanks to the heavy lifting done by you. 🙏 The key is not to fight the gluee; just find out what it wants and make it happy, and you seem to have that under control. Use macros to clean up the resulting mess, as you know. So I just pull the master branch, change the version, and lein install?

kennytilton23:07:53

Hey, it works. 🙂 You just made my birthday. 🎉