Fork me on GitHub
#rum
<
2021-05-21
>
michihuber07:05:44

Hi there, can anybody help me with a macro outputting a rum component? I want to add some sugar for standard components in my app, that always require the same set of mixins

(rum.core/defcs yo < editor.components.mixins/dispatching ,,,
  [a b]
  [:div "hello"])
Should become:
(defco yo [a b]
  [:div "hello"])
with this macro:
(defmacro defco [sym args & body]
  `(def
     ~sym
     (rum.core/build-defcs
       (fn ~(cons args body))
       [editor.components.mixins/dispatching ,,,]
       ~(str sym))))
the two forms above macroexpand-1 to exactly the same form, but my macro throws a react error, because :div is interpreted as a child (but react cannot render objects (keyword object in this instance)). any ideas?

Azzurite12:05:10

I've also struggled with this and gave up (but mostly because my macro knowledge was terrible, I didn't run into the same issue)

Azzurite12:05:32

I took you having this problem as well as a challenge and tried again, try this please:

(defmacro defco [sym args & body]
  `(rum.core/defc
     ~sym
     ~'< ALL_YOUR_MIXINS
     ~args
     ~@body))

Azzurite14:05:05

I've also arrived myself at this version, which you can probably adjust to your liking:

(defn insert
  "Inserts an element into a collection at the given index"
  [coll idx elem]
  (concat
    (take idx coll)
    [elem]
    (drop idx coll)))

(defmacro def-styled
  "rum/defc but automatically adds the reactive mixin"
  [sym & args]
  (let [docstring (when (= (second args) '<)
                    (first args))
        filtered-args (if (= (first args) '<)
                        (rest args)
                        (if docstring
                          (nthrest args 2)
                          args))
        definition `(rum/defc
                      ~sym
                      ~'< reactive
                      ~@filtered-args)]
    (if docstring
      (insert definition 2 docstring)
      definition)))

michihuber07:05:21

awesome, thank you, @UCULU82G3

michihuber07:05:42

when I change :div to "div" it works (showing div as a string in the dom, but no error)