clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
Grigory Shepelev 2020-10-16T07:34:24.499400Z

Any help? The reply is not helpful. I am using re-frame default template with in-build hiccup and I want to use google-material components in my app in idiomatic style:

(ns re-frame-blog.views
 (:require
  [re-frame.core :as re-frame]
  [re-frame-blog.subs :as subs]
  [material-components-web :as material]))
(defn home-panel []
(let [name (re-frame/subscribe [::subs/name])]
  [:div 
   [:h1 (str "Hello from " @name ". This is the Home Page.")]
   [material/card ;; say I want to use material card here
    [:p "text"]]
   [:div
    [:a {:href "#/about"}
     "go to About Page"]]]))

p-himik 2020-10-16T07:40:02.499500Z

MDC Web is a library that relies on the existing DOM. It's not a great fit for React (which Reagent uses. Which, in turn, is used by re-frame). Because of that (and unless there's some documentation that I can't find), you cannot use it in Hiccup directly as in your example. You have to either use refs everywhere and manually create all the components just like in the example in the documentation, or you have to follow the other example where they just create the DOM with the necessary data attributes and just let MDC to automagically patch those DOM elements.

p-himik 2020-10-16T07:40:35.499700Z

Have you ever used jQuery? Well, MDC Web is exactly like that.

p-himik 2020-10-16T07:41:55.499900Z

You might be interested in this, which appears to bring MDC Web closer to React: https://github.com/jamesmfriedman/rmwc

Grigory Shepelev 2020-10-16T07:42:56.000100Z

Yes, I used JQ few times. I left behind state of modern webdev for couple years.

p-himik 2020-10-16T07:43:00.000300Z

Alternatively, you can use a library that was intended to work with React in the first place, like Material UI for example.

p-himik 2020-10-16T07:43:43.000500Z

jQuery is not used with React in general. React is about mutating state that's separate from the components. jQuery is about mutating the DOM directly.

Grigory Shepelev 2020-10-16T07:43:52.000700Z

So. If I use react (that re-frame does implicitly) I need to look for "react-builds" of css libs?

p-himik 2020-10-16T07:44:28.000900Z

You need to look for something that can be used with React. You can use MDC Web with React. But it's either painful or requires an additional wrapper.

Grigory Shepelev 2020-10-16T07:47:07.001100Z

Ok. Thanks. Clojurescript - js interop is very complicated IMHO. Especially if I had no experience with react. I'm just trying to figure the stuff out.

Grigory Shepelev 2020-10-16T07:52:48.001500Z

So. Given that I installed rmwc with npm. How do I use it with re-frame and hiccup? As simple as I wrote? Do I have to add something in project.cljs ?

p-himik 2020-10-16T07:55:31.001700Z

"Clojurescript - js interop is very complicated IMHO" - but your issue has absolutely nothing to do with CLJS/JS interop. JS interop is quite simple, in fact. You can access JS objects from CLJS just fine, and you can export any CLJS symbol to JS just fine as well.

p-himik 2020-10-16T07:57:07.001900Z

This link is still relevant if you still use shadow-cljs: https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages You also need to read this: https://github.com/reagent-project/reagent/blob/master/doc/InteropWithReact.md

p-himik 2020-10-16T07:58:40.002200Z

The section "Creating Reagent "Components" from React Components" is of extra interest to you. But the whole document is still a must. Including the links at the bottom, especially since they contain examples.

Kasey Speakman 2020-10-16T08:24:53.007600Z

Ok, I feel like I am taking crazy pills. I'm using comp with partials to define a function in ClojureScript. (It's an experiment, not something I want to do routinely.) If I immediately invoke the function it works. But if I assign a name to it with def and then try to invoke that with an argument it always just returns whatever is passed into it. Basically becomes identity.

(defn test- [trait f value]
  (if-some [value (f value)]
      value
      {::error trait}))

(defn test-and- [trait f value]
  (if (contains? value ::error)
    value
    (test- trait f value)))

((comp (partial test-and- :keyword keyword)
       (partial test- :required not-empty)) "")
=> #:myns.core{:error :required}

((comp (partial test-and- :keyword keyword)
       (partial test- :required not-empty)) "asdf")
=> :asdf

(def tmpf (comp (partial test-and- :keyword keyword)
                (partial test- :required not-empty))

(tmpf "")
=> ""

Kasey Speakman 2020-10-16T08:28:50.008Z

Nvm, was missing a paren

Grigory Shepelev 2020-10-16T08:41:44.008100Z

Having read that I still don't understand how do I call a component?

(ns re-frame-blog.views
(:require
  [re-frame.core :as re-frame]
  [re-frame-blog.subs :as subs]
  ["rmwc" :as material]))

(defn home-panel []
(let [name (re-frame/subscribe [::subs/name])]
  [:div 
   [:h1 (str "Hello from " @name ". This is the Home Page.")]
   (material/card [:p "text"])
   [:div
    [:a {:href "#/about"}
     "go to About Page"]]]))

Grigory Shepelev 2020-10-16T08:42:00.008300Z

How do I access card for example?

p-himik 2020-10-16T08:52:57.008500Z

First of all, what do you mean by "access"?

Grigory Shepelev 2020-10-16T08:54:08.008700Z

I had some previous experience with VueJs about 1.5 y. ago. After webpack setup I could just import card in ES2015 style on top and then just use <card> ... </card>

p-himik 2020-10-16T08:57:38.008900Z

I see. ["rmwc" :refer [Card]]. Better yet, ["@rmwc/card" :refer [Card]] to avoid pulling the whole library when you need just Card.

p-himik 2020-10-16T08:58:36.009100Z

Note that I did check those :require vectors just in case, but they both are just direct translation of the rmwc documentation using that table in the shadow-cljs user's guide.

p-himik 2020-10-16T08:59:07.009300Z

And then use it as [:> Card {...} ...], just as Reagent documentation says.

Grigory Shepelev 2020-10-16T09:09:57.009500Z

Thnx. I will try in 15-10 minutes.

borkdude 2020-10-16T10:13:46.010600Z

Is there a JS of CLJS library which implements a widget similar to "Apply labels to this issue" in Github?

Grigory Shepelev 2020-10-16T11:39:28.010700Z

Now I can see with element inspection (in Browser) that it uses the proper classes and stuff when I call elements like that: [:> Card {..} ...] Thanks. But it doesn't use styles from material design.

p-himik 2020-10-16T11:45:42.011Z

Have you read the page at https://rmwc.io/installation?

Grigory Shepelev 2020-10-16T11:52:03.011200Z

Do I have to use webpack?

p-himik 2020-10-16T11:53:30.011400Z

No. You can include CSS directly via HTML or some CLJS code (there are libraries for that).

Grigory Shepelev 2020-10-16T11:54:16.011600Z

I want it with cljs.

p-himik 2020-10-16T11:59:32.011800Z

Well, then you will have to find a library that can include CSS directly via code. I don't know of any offhand.

Grigory Shepelev 2020-10-16T12:02:15.012Z

re-frame has this one

:garden {:builds [{:id           "screen"
                     :source-paths ["src/clj"]
                     :stylesheet   re-frame-blog.css/screen
                     :compiler     {:output-to     "resources/public/css/screen.css"
                                    :pretty-print? true}}]}

Grigory Shepelev 2020-10-16T12:03:13.012400Z

As far as I got this handles the css. I should add "/node_modules/material-components-web/dist" to :source-paths and something to :stylesheet. What exactly.

p-himik 2020-10-16T12:14:07.012600Z

TBH, I feel like on your "road to CLJS enlightenment" you have skipped quite a few steps and now it creates a lot of confusion. re-frame is a state management library. It has nothing to do with CSS. The snipped you provided above is handled by some build tool apparently - I don't know what. But it uses the :garden keyword, which hints that it uses this library: https://github.com/noprompt/garden The library by itself doesn't embed CSS in your page - it just renders CSS strings. OK, seems that you're using the re-frame template. IMO this is pretty much the worst way to learn CLJS simply because it not just allows you to skip steps but it actually forces you to. My advice: put MDC Web aside for now, build a small app without any libraries. Add some simple CLJS lib to it. Add some simple NPM lib to it. Gradually increase the complexity while making sure that you understand what's going on at each step.

p-himik 2020-10-16T12:18:53.012900Z

BTW the above :garden configuration just tells lein-garden plugin to compile whatever Garden CSS definitions are in re-frame-blog.css/screen into regular CSS and save the result into "resources/public/css/screen.css". It doesn't embed CSS into your page automatically. You still have to include it in your HTML somehow. Which the template does right here: https://github.com/day8/re-frame-template/blob/master/src/leiningen/new/re_frame/resources/public/index.html#L11

Saikyun 2020-10-16T16:09:53.014900Z

I suddenly started getting 100s of Cannot infer target type in expression (. (. obj -userData) -tile) in my project. it wasn't like this yesterday when I left it. anyone who has a clue as to what might have happened?

Saikyun 2020-10-17T18:10:55.068200Z

nope, I haven't set it to true as far as I can see... when the issue does arise, how do I figure out what to do about it?

Saikyun 2020-10-19T10:02:44.116300Z

thanks, I'll take a look

victorb 2020-10-16T16:55:03.015Z

Did you maybe add (set! *warn-on-infer* true) somewhere in your code?

victorb 2020-10-16T16:55:49.015200Z

if you set that to false it should stop giving you the warning. But probably you wanna leave it on, and actually fix the cause. Google Closure Compiler sometimes does the "wrong thing" and these warnings can help you pinpoint where things are funky

macrobartfast 2020-10-16T17:20:55.016300Z

(js/alert "foo") is working fine but not (js/console.log "foo"), I tried it in two browsers… thoughts about how to troubleshoot this? I get nil as a response to the log statement, if that’s useful.

dpsutton 2020-10-16T17:22:00.016600Z

did you open up the browser console?

macrobartfast 2020-10-16T17:22:11.016800Z

I did…

macrobartfast 2020-10-16T17:24:06.017800Z

I’m evaluating the statement inline… l also tried it in the Emacs cljs REPL.

dpsutton 2020-10-16T17:24:36.018100Z

do you have multiple browser tabs open?

dpsutton 2020-10-16T17:25:40.018200Z

macrobartfast 2020-10-16T17:26:37.018700Z

I do… but I solved it!

macrobartfast 2020-10-16T17:27:18.019500Z

I guess you have to select the info button on the left in Chrome dev tools… they have you select your filters there now.

macrobartfast 2020-10-16T17:28:07.020300Z

in other words, I was filtering it out (but the options are no longer at the top where I used to expect them).

macrobartfast 2020-10-16T17:45:12.020400Z

By the way, I had an awesome time last night and this morning building a simple site interactively… so cool… all because of your help getting me over the setup hurdle. It’s so cool when this all works!

dpsutton 2020-10-16T17:49:24.020600Z

i'm glad you're up and running!

Ronny Li 2020-10-16T19:19:08.023Z

Hi does anyone know how to resolve this figwheel error?

[Figwheel] Successfully compiled build dev to "target/public/cljs-out/dev/main.js" in 35.941 seconds.
[Figwheel] Bundling: npx webpack --mode=development target/public/cljs-out/dev/main.js -o target/public/cljs-out/dev/main_bundle.js
[Figwheel:SEVERE] Bundling command failed
asset main.js 644 bytes [compared for emit] (name: main)

ERROR in main
Module not found: Error: Can't resolve 'target/public/cljs-out/dev/main.js' in '/Users/abc/demo'

webpack 5.1.2 compiled with 1 error in 47 ms
I'm following the Figwheel instructions for https://figwheel.org/docs/npm.html and my dev.cljs.edn file looks like this:
{
 :main demo.core
 :target :bundle
 :bundle-cmd {:none ["npx" "webpack" "--mode=development" :output-to "-o" :final-output-to]}
 }
Thanks in advance!

athomasoriginal 2020-10-21T00:40:45.160Z

If no one answered this yet, there is an open issue for this and I believe the solutions were outlined recently in #figwheel-main

Ronny Li 2020-10-22T12:37:46.198500Z

Thanks! Copying the link to the solution here for others: https://clojurians.slack.com/archives/CALJ3BFLP/p1603126703062600?thread_ts=1603113368.056000&cid=CALJ3BFLP

2020-10-16T21:13:03.025400Z

I’m curious, what makes the execution of the following two approaches behave so differently? (reagent)

(defn dummy
  []
  (rdbg/log "hi")
  (let [num (r/atom 1)
        _ (js/setTimeout #(reset! num 2))]
    (rdbg/log "bye")
    [:pre @num]))


(defn dummy
  []
  (rdbg/log "hi")
  (let [num (r/atom 1)
        _ (js/setTimeout #(reset! num 2))]
    (fn []
      (rdbg/log "bye")
      [:pre @num])))
in the 1st case, i had missed out on returning a function (form 1 component) .. and what i saw on my console logs was continous “hi/bye” logs suggesting the component is getting rendered again and again (the ratom was updated in a settimeout yes, but it is done for the 2nd example as well) the 2nd one worked perfectly fine (as it should) .. what exactly is happening under the hood?

lilactown 2020-10-16T21:26:17.026700Z

When you return a function from a reagent component, on subsequent renders it will only run the inner function

lilactown 2020-10-16T21:27:36.028900Z

This allows you to construct objects (like an atom) when the component initially mounts, which will be kept alive and referenced until the component unmounts

lilactown 2020-10-16T21:28:24.030Z

Without this, like in your first case, it will construct a new atom every render, which will always contain the initial state

2020-10-16T21:34:02.030100Z

ohh, so if a function returns a hiccup then that function is the renderer. and since i updated the ratom, reagent reran the “dummy” function (which is the renderer because i returned a hiccup and not a function)

2020-10-16T21:34:23.030300Z

need to dig more into the reagent interpreter now!

2020-10-16T21:34:25.030500Z

thanks

2020-10-16T21:35:00.030700Z

that explains why the continuous logs

2020-10-16T21:47:07.040300Z

hi, i’ve been scratching my head trying to implement the following (finally got something working but was wondering if there’s a better way) i have a parent-child component hierarchy, and there’s an IntersectionObserver that has to be initialized with the parent DOM element (so i place this in the ref callback of the parent). Now, I need to store this observer in a atom/ratom/some local state basically, so whenever child components mount, their ref callback runs and uses this observer to register themselves. but given the way react mounts component hierarchy (child first parent last), the ref callback of child sees the observer as nil (default) (because the parent ref callback hasn’t been called yet, so (. @observer observe dom)) will fail)

(defn log-viewer
  []
  (let [observer (r/atom nil)
        nums (r/atom (range 30))] ;; ignore the nums
    (fn []
      [:div {:ref (fn [dom]
                    (if-not dom
                      (when @observer
                        (. @observer disconnect))
                      (reset! observer
                              (js/IntersectionObserver.
                               rdbg/log
                               {:root dom
                                :threshold 1}))))}
       (when @observer
         (for [x @nums]
           ^{:key x} [:pre {:ref (fn [dom]
                                   (when dom
                                     (. @observer observe dom)))} x]))])))
right now as a workaround(?) i used a ratom and put the childs within a when @observer condition. but i’m curious to know if there is a better way

macrobartfast 2020-10-16T22:48:35.040600Z

so sweet, the approach to setting up a project in the talk… I prefer not using lein templates if I can…

macrobartfast 2020-10-16T22:48:59.040800Z

is there a way to connect emacs to the repl? I used to use cider-connect to nrepl.

macrobartfast 2020-10-16T22:50:35.041Z

In the talk, for interactivity, it looks like you use the terminal prompt repl… not sure. I did the non-repl version and quickly had a webpage.

dpsutton 2020-10-16T22:52:07.041200Z

correct. the talk was a lightning talk so i had 5 minutes. didn't want to get into editor interactivity

macrobartfast 2020-10-16T22:52:27.041400Z

oh c’mon… you could have taught them emacs in 5 minutes!

dpsutton 2020-10-16T22:52:49.041600Z

oh. in this case i did it just to be quick. if you cider-jack-in-cljs your repl will be connected

macrobartfast 2020-10-16T22:52:57.041800Z

SWEET!

macrobartfast 2020-10-16T22:53:25.042Z

Who is it at Cognitect who does all their development at the repl prompt?

macrobartfast 2020-10-16T22:53:28.042200Z

Jedi.

macrobartfast 2020-10-16T22:54:20.042400Z

ok, trying that now.

macrobartfast 2020-10-16T22:56:37.042600Z

omg, it all works.