Search code examples
clojureom

Test if Clojure Om Next component satisfies? a protocol


In Clojure (not ClojureScript), how can I check that a given component implements a protocol?

(defui MyComp
  static my-protocol
  (aaa [this] []))

(satisfies? my-protocol MyComp) ;; false
(satisfies? om.next.protocols/IReactChildren MyComp) ;; false
;; but
(.aaa ( MyComp nil nil nil nil)) ;; []

Solution

  • As far as I understand now, this is not supported directly by om.next, since defui does not behave exactly like defrecord.

    One way (used by untangled) is to put the implementation of the protocol in the metadata. Conversation with tony kay:

    tony.kay [6:02 PM] So defui in clj land adds the "protocol" things to metadata just a sec... https://github.com/untangled-web/untangled-client/blob/0b2fdfec1f0dde2d1d95b5a4d092131ca6fdc8f4/src/untangled/client/core.cljc#L90-L96 this is why we need functions like get-initial-state. We can call the protocol ones in cljs, but not in clj because js allows his macro to hack them into place Om components have to be stock React components for interop, so we don't actually use protocols per-se, just emulate the syntax this is part of the cleanup work that we need to comb over in a lot of our docs/guide for sever-side rendering. You cannot, for example, call initial-state in your UI and expect clj-land to like it but many of our examples were written before it existed, and are now technically wrong if you want to do ss rendering

    This is also how it is done inside om.next for server-side rendering.

    It can also be seen in om-css https://github.com/ladderlife/om-css/blob/dd19235dabca74db1669504fff941ff97abddcc4/src/main/om_css/core.cljc#L240-L242

    Unfortunately since these approach require overwriting defui they do not compose together very well.