Search code examples
clojureclojurescript

how to customise the print function for native objects in clojurescript


I'm looking to customize how a react element is displayed, this is the code:

(require ["react" :as react])    

(defn react-element? [obj]
  (if-let [sym (aget obj "$$typeof")]
    (= js/Symbol
       (type sym))))

(extend-protocol IPrintWithWriter
  object
  (-pr-writer [obj writer _]
    (js/console.log "hello")
    (cond (react-element? obj)
          (write-all writer
                     (-> (js->clj obj)
                         (dissoc "$$typeof")
                         str))

          :else
          (write-all writer (str obj)))))

(react/createElement "h2" nil "Hello, World!")

I'm expecting the output to be

{:type "h2", :key nil, :ref nil, :props {:children "Hello, World!"}}}

but it still prints out the normal #js element:

#js {"$$typeof" Symbol(react.element), 
     :type "h2", :key nil, :ref nil, 
     :props #js {:children "Hello, World!"}, :_owner nil}

Is there a way to customize this behaviour?


Solution

  • The root cause is that in the standard lib printing code, implements? is used and satisfies? is not used. This effectively limits printing overrides to things that are not native types. (implements? doesn't doesn't work on native types).

    This may not be intentional and may be fixed with https://dev.clojure.org/jira/browse/CLJS-2812