Fork me on GitHub
#helix
<
2021-08-25
>
kennytilton13:08:33

So things are going great marrying Matrix to Helix and I want to do the DRY thing and write a macro to write some macros. The problem is providing a react native type such as rn/View to the macro. Story here: https://clojurians.slack.com/archives/C03S1KBA2/p1629896337345000 But now I notice that helix $ has a bit of flexibility when it comes to the type parameter: "The $ macro takes a component type (string, keyword, or symbol referring to a Component)" The examples I see are "div" and :div. I bravely attempted "View" and :View to no avail. Is there some way to use CLJS reflection to get to the react native rn/View in generate CLJS? 🤞

kennytilton13:08:43

btw, the brave attempts ended with "Invariant Violation: View config not found for name View."

lilactown14:08:37

the react native renderer doesn't accept strings

lilactown14:08:30

you have to provide it a reified component (i.e. a function, class, or one of the values exported from react or react-native like react-native/View)

lilactown14:08:19

react-dom and other renders are different, they accept "div" as a type

kennytilton15:08:01

I just tested this: (defmacro View [mx-props jsx-props & children] `(tiltontec.model.core/make :myapp.mxreact/mxrn.elt :sid (swap! myapp.mxreact/sid-latest inc) :kids (tiltontec.model.core/cFkids ~@children) :rendering (tiltontec.cell.core/cF (helix.core/$ (mxfnc (apply helix.core/$ (when true rn/View) ~jsx-props {} (doall (map #(tiltontec.model.core/mget % :rendering) (tiltontec.model.core/mget ~'me :kids))))))) ~@(apply concat (into [] mx-props)))) ...and I think it worked. :) I can replace the (when true... with a case statement (case ~rn-ty :View rn/View :SafeAreaView etc) and get pretty much the DRY I was after. 🤞

kennytilton15:08:34

No, not CASE, a big COND or sth.

kennytilton20:08:31

I am starting to think I should unpack the helix.core/$ macro and write a macro that expands into .createElement yada yada. This will not be as powerful, but I am really just trying to get to the react native elements, and plan to use Matrix magic to make the react native elements easily programmable. One thing that puzzles me is that the CLJS helix.core defines get-react but does not use it in forms like: (apply create-element type' nil args) ...where create-element is just (def create-element react/createElement) But I know next to nothing about interop so I will not worry about it. 🙂 Current plan is to try creating some RN elements with some form of createElement and then worry about macros. Thanks for a huge leg up on RN from CLJS!

lilactown20:08:53

IIRC (get-react) was a micro-optimization that emitted slightly nicer code

lilactown20:08:08

haven't tested it in the case of (apply ,,,)

kennytilton23:08:00

Ah, I found a reasonable compromise to get DRY and stay with the helix.core/$ macro:

(defmacro define-view-macro [gen-type]
  `(defmacro ~gen-type [mx-props# jsx-props# & kids#]
     `(tiltontec.model.core/make :myapp.mxreact/mxrn.elt
        :sid (swap! myapp.mxreact/sid-latest inc)
        :kids (tiltontec.model.core/cFkids ~@kids#)
        :rendering (tiltontec.cell.core/cF
                     (helix.core/$ (myapp.mxrgen/mxfnc
                                     (apply helix.core/$
                                       (get {:View         rn/View
                                             :SafeAreaView rn/SafeAreaView} ~~(keyword gen-type))
                                       ~jsx-props#
                                       {}
                                       (doall
                                         (map (fn [~'mapkid#]
                                                (tiltontec.model.core/mget ~'mapkid# :rendering))
                                           (tiltontec.model.core/mget ~'~'me :kids)))))))
        ~@(apply concat
            (into [] mx-props#)))))
I will have another one for atomic widgets (no children). I just have to type in an entry translating each keyword :View to the rn/View etc. Now I can (define-view-macro View). Next up will be yet another trivial macro so I can (define-view-macros View SafeAreaView ScrollView). Thx again for Helix. 🙏