Sometimes when you use a third-party JS/React library from NPM, it doesn't only provide you with React components that are easily usable from UIx, but it may also export React hooks or functions that return JS data. To access data fields in JavaScript objects, you have to use ClojureScript's interop syntax.
(ns app.core
(:require [uix.core :as uix :refer [defui $]]
["react-hook-form" :as rhf]))
(defui register-form []
(let [form (rhf/useForm)
first-name-props (.register form "first-name")
last-name-props (.register form "last-name")]
($ :form {:on-submit (.-handleSubmit form)}
($ :input first-name-props)
($ :input last-name-props))))
To make things more idiomatic, UIx comes bundled with cljs.bean — a library that implements Clojure's collection abstractions for JS data types. It is more performant than js->clj since values are transformed lazily, at read time.
Note how you can use associative destructuring on JS object wrapped with bean:
(ns app.core
(:require [uix.core :as uix :refer [defui $]]
[cljs-bean.core :as bean]
["react-hook-form" :as rhf]))
(defn use-form []
(bean/->clj (rhf/useForm)))
(defui register-form []
(let [{:keys [register handleSubmit]} (use-form)
first-name-props (register form "first-name")
last-name-props (register form "last-name")]
($ :form {:on-submit handleSubmit}
($ :input first-name-props)
($ :input last-name-props))))
There's a gotcha however, similar to js->clj, bean transformation only works for plain JavaScript objects. Meaning that class instances won't convert to Clojure maps, because there's inheritance that can't be expressed with maps.
In such case bean will just return the instance unmodified:
(def img (bean/->clj (js/Image.)))
;; `img` remains unmodified js/Image instance
(.decode img)
As a rule of thumb: use bean to consume data, and interop syntax to call into JS APIs (whether they are native or provided by JS libraries).