         class' (when class
                  (string/replace class #"\." " "))]
     (assert tag (str "Unknown tag: '" hiccup-tag "'"))
-    [tag (when (or id class')
-           [id class'])]))
+    #js{:name tag
+        :hasIdClass (or (some? id) (some? class'))
+        :idName id
+        :className class'}))
 
 (defn fn-to-class [f]
   (assert (ifn? f) (str "Expected a function, not " (pr-str f)))

                            #js{} x)
        :else (to-js-val x)))

(defn set-id-class [props [id class]]
  (when (some? id)
    (let [pid (.' props :id)]
      (.! props :id (if (some? pid) pid id))))
  (when (some? class)
    (let [old (.' props :className)]
      (.! props :className (if (some? old)
                             (str class " " old)
                             class)))))

(defn convert-props [props id-class]
  (if (and (empty? props) (nil? id-class))
    nil
    (let [objprops
          (reduce-kv (fn [o k v]
                       (let [pname (cached-prop-name k)]
                         (aset o pname (convert-prop-value v)))
                       o)
                     #js{} props)]
      (when (some? id-class)
        (set-id-class objprops id-class))
      objprops)))



;;; Props conversion

(def prop-name-cache #js{})

(defn obj-get [o k]
  (when (.hasOwnProperty o k)
    (aget o k)))

(defn cached-prop-name [x]
  (if (or (string? x)
          (not (implements? INamed x)))
    x
    (if-let [s (obj-get prop-name-cache (name x))]
      s
      (aset prop-name-cache (name x) (undash-prop-name x)))))

(defn convert-prop-value [x]
  (cond (string? x) x
