ClojureScript Dos and Donts: clj->js

clojurescript

#1

New micro blogpost about the clj->js function. Feedback welcome!


#2

Very interesting! This blog post from mike fikes has some benchmarks that support your point http://blog.fikesfarm.com/posts/2017-11-09-avoid-converting-javascript-objects.html.

What I would really like to have is a macro that can do what clj->js is doing for static values.

I’m working on a react-native app. We have a namespace where we define all the styles we are using through the app, it goes a little like this:

;; styles.cljc

;; Colors
(def green  "#47a8d8")
(def orange "#F16913")

;; Dimensions
(def gutter 10)
(def radius 2)

;; Actual style for a component
(def button-base {:flex 0
                  :padding gutter
                  :borderRadius radius})

(def button-default (assoc button-base :backgroundColor green))
(def button-warning (assoc button-base :backgroundColor orange))

I want to keep the expressive power of clojure to define/compose/merge those style declarations. But at the same time, I would like to be able to call something like clj->js at compile time to emit the js litterals (or throw an exception if the value cannot be statically determined at compile time).

;; some_component.cljs
(react/createElement react-native/view
                     #js {:style (macro-clj->js styles/button-default)})

I cannot seem to find how to do that… Emitting #js inside of a macro would not work, as it is a reader literal.

Any idea?


#3

@chpill not a direct answer, but check lookbook for some inspiration about RN stylesheets composed at compile time.


#4

I added a link to Mike’s blog post, thanks for the pointer.


#5

@chpill You can use js-obj macro to emit JS objects from macros.

But in your example, (macro-clj->js styles/button-default) wouldn’t work because the result of assoc is only available in runtime (and the macro only sees the symbol).


#6

@juhoteperi if the styles namespace is declared in a cljc file, the style values would be available to the macro, wouldn’t they?


#7

Macros work on Clojure forms - they do not introspect vars.

The best way is to wrap button-default and button-warning in a clj->js so that it happens once, at def-time.

I’ve experimented with this optimization a bit with the hiccup compiler I’m building - it will shallowly convert map literals to JS objects, but will wait until runtime to convert vars.


#8

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.