Props validation

While in React it's common to use PropTypes for runtime validation or TypeScript for static type checking, in Clojure we can leverage :pre conditions to assert component's props at runtime.

Here's a typical example using defn.

In UIx, the syntax of the defui macro inherits most properties of defn, including pre conditions.

(defui button
  [{:keys [children on-click]}]
  {:pre [(fn? on-click)]}
  ($ :button {:on-click on-click}
    children))

To improve things further and leverage clojure.spec for rich data validation and helpful error messages, it's recommended to use adamrenklint/preo library.

Most likely you don't want those runtime checks in production. Make sure :elide-asserts compiler option is set to true, unless if you are using shadow-cljs, where the option is set to true for release builds by default.

To validate React children you can use the following spec.

(s/def :react/element
  (s/or
    :string string?
    :number number?
    :nil nil?
    :element react/isValidElement ;; for actual React elements
    :elements :react/elements)) ;; for nested collection of elements

;; a collection of child elements
;; can be either JS array of Clojure's sequential collection
(s/def :react/elements
  (s/coll-of :react/element :kind #(or (array? %) (sequential? %))))

;; `children` can be either a single element
;; or a collection of elements
(s/def :react/children
  (s/or :element :react/element
        :elements :react/elements))