Fork me on GitHub
#clojurescript
<
2019-07-11
>
oskarkv02:07:09

Math in JavaScript is an object, right? How can I access that object in ClojureScript? I know I can do Math/pow for example to call a method of it, but how can I view the object without calling any methods? Just doing js/Math results in #js {} which is an empty object? I'm confused. 😛

nenadalm20:07:00

That is because Math properties are not enumerable: http://zduck.com/2013/non-enumerable-properties-in-javascript/. You can use getOwnPropertyNames (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames) to get list of properties. So if you wanted map of properties, you could do:

(->> (.getOwnPropertyNames js/Object js/Math)
       (map (fn [prop]
              [prop (goog.object/get js/Math prop)]))
       (into {}))

deadghost03:07:18

@oskarkv view as a clj hashmap?

deadghost03:07:40

(js->clj js/Math) should do it

deadghost04:07:07

methods and properties should be accessed as you'd typically do it

deadghost04:07:32

(.abs js/Math -1)

deadghost04:07:55

(.-E js/Math)

oskarkv04:07:35

@deadghost (js->clj js/Math) returns {}

deadghost04:07:57

@oskarkv are any props or methods working?

oskarkv04:07:06

Yes, they work fine

deadghost04:07:28

how are you viewing the object?

oskarkv04:07:42

I don't understand

deadghost04:07:54

are you looking at it with the browser console?

oskarkv04:07:03

No, with CIDER/Emacs

deadghost04:07:10

are you compiling it to target the browser?

deadghost04:07:00

(.log js/console js/Math) somewhere in code that will get run in the browser

deadghost04:07:04

and check the console

deadghost04:07:48

I've actually never got cljs hooked up into cider

oskarkv04:07:54

Yeah logging like that showed the JS object

Saikyun05:07:03

are there any projects working on running a self-hosted cljs repl in the browser/in node/electron? 🙂

Saikyun05:07:30

I've played around a bit with lumo, but from what I can tell, you can't really require it from node

Saikyun05:07:54

I've read a little on replumb, and I think it's in the right direction, but I don't actually understand what it does

Michaël Salihi07:07:30

Hi guys ! Question : when using Reagent and cljs-ajax library, what is better place to put loading state ? On local state component Reagent atom or on global state ? Can I use form-2 component like this ? Without using form-3's :component-did-mount ?

(defn my-component []
  (let [is-loading? (reagent/atom true)]
    (fetch-from-api?) ;; <-- cljs-ajax call
    (fn []
      (if @is-loading?
        [:p "loading..."]
        [:p "Content loaded"]))))
Thx 🙂

Michaël Salihi07:07:31

Like that it works, but I must pass the ratom state in the fetch-from-api argument and use :finally to reset! is-loading to nil and I'm sure is not clean, isn't it ? (fetch-from-api is-loading?)

Michaël Salihi07:07:55

(defn fetch-from-api
  [id is-loading?]
  (let [url (str "" id "?api_key=" api_token "&language=fr")]
    (GET url
      {:handler #(reset! film %)
       :finally #(reset! is-loading? nil)
       :error-handler (fn [{:keys [status status-text]}]
                        (js/console.log status status-text))
       :response-format :json
       :raw true})))

kwrooijen09:07:57

Greetings, I’m requiring an NPM package (material-ui, to be precise) and I learned that if I want to import a single icon I can use the following require line:

Clojure
["@material-ui/icons" :refer [Add]]
This works, however it imports all icons withing @material-ui/icons instead of just Add (approx. 5000) The alternative route to fix this is:
Clojure
["@material-ui/icons/Add" :default Add]
Now we only require Add and it all works. My question is, if I want to import 10 icons I’d have to write this 10 times. Is there by any chance a require key like :refer but only imports what I need?

kwrooijen09:07:14

I honestly doubt it but I thought it was worth asking anyway

Alexis Vincent12:07:12

Hi guys, Im trying to build a lib and I need to be able to register a handler for dismount from within a reagent component, without being able to control the component call site. I want to be able to do something like this.

(defn component []
  (on-dismout #(js/console.log "dismounted"))
  (fn []
    [:div]))
I’ve tried a few things, but none of them are ideal. this kind of gets there
(defn on-dismount [f]
  (let [reaction (.-cljsRatom (r/current-component))]
    (ratom/add-on-dispose! reaction f)))
but cljsRatom is not defined on first render.
(.-isMounted (.-updater (r/current-component) ) (r/current-component)
requires me to register a polling service and won’t be particularly quick This also kind of works
(defn on-dismount [f]
  (let [id (rand-int 1000)
        reaction (ratom/make-reaction (constantly true)
                                      :on-set (constantly nil)
                                      :on-dispose f)]
    @reaction
    reaction))

But the caller needs to keep derefing the return value, in render cycle Anyone have an idea?

danielneal12:07:15

I only read about it today, but I think you might be able to use with-let and a finally block

Alexis Vincent12:07:52

yeah! but unfortunately I think that requires to change call site, so you’re in the same predicament as a higher order component

Alexis Vincent12:07:53

maybe not…

(defn mouse-pos []
  (r/with-let [pointer (r/atom nil)
               handler #(swap! pointer assoc
                               :x (.-pageX %)
                               :y (.-pageY %))
               _ (.addEventListener js/document "mousemove" handler)]
    @pointer
    (finally
      (.removeEventListener js/document "mousemove" handler))))

(defn tracked-pos []
  [:div
   "Pointer moved to: "
   (str @(r/track mouse-pos))])

Alexis Vincent12:07:26

Thanks, i’ll experiment

Alexis Vincent12:07:04

yeah, same problem. Need to keep derefing the reaction for it to not trigger the dispose immediately

danielneal13:07:12

oh you need to write the actual function on-dismount that takes another function, rather than writing a component that runs some code on dismount?

lepistane22:07:13

Hi guys i got question about interop with react semantic ui i find strange behavior https://codesandbox.io/s/l2mz8yljl7?module=/example.js is the example and i am playing with concept of knowing if view is mobile. so i am using

(-> ui/Responsive
      .-onlyMobile
      .-maxWidth)
and that works but i wanted to use (goog-obj/get ui/Responsive #js ["onlyMobile" "maxWidth"]) but that is nil then i used (goog-obj/get ui/Responsive #js ["onlyMobile"]) and i get
#js {:minWidth 320, :maxWidth 767}
then i would have to use something like
(:maxWidth (js->clj (goog-obj/get ui/Responsive #js ["onlyMobile"])
                                             :keywordize-keys true))
or
(get (js->clj (goog-obj/get ui/Responsive #js ["onlyMobile"])) "maxWidth")
in this weird or i am doing something wrong?

Michaël Salihi22:07:01

Hello @lepistane You can use getValueByKeys : (goog-obj/getValueByKeys ui/Responsive #js ["onlyMobile" "maxWidth"])

👍 1
Michaël Salihi22:07:14

From the doc : > Get a value from an object multiple levels deep

👍 1