Fork me on GitHub
#clojurescript
<
2021-03-31
>
Trevor Martin03:03:46

Hi šŸ‘‹, I'm new to Clojurescript and I've written a neat little reagent app that makes a call to an API, stores the result in an ratom and renders the information accordingly. super-cool stuff. I'm loving it. I've become accustomed to storing things like the BASE_URL to any given API within process.env.VARIABLES how do I access these from cljs ? or is there a better way to do this ? is it build-tool specific ?

tvirolai11:03:20

Environ (https://github.com/weavejester/environ) is a good option for doing this. It combines parameters from different sources into a single map for processing in the application.

p-himik13:03:52

That will work only if process.env is set correctly. And you can access keys within process via goog.object - no need to extra libraries unless you need to share the same code with CLJ. As an alternative approach, you can use goog-define and set its values in compile time. This would depend on the build tool. Relevant documentation for shadow-cljs: https://shadow-cljs.github.io/docs/UsersGuide.html#shadow-env

Trevor Martin20:03:55

thanks for that insight, if I understand correctly,

(goog-define BASE_URL "")
will set a default value to be overwritten at compile time ... and that value is read from shadow-cljs.edn
...

 :builds
 {:app
  {:target     :browser
   :output-dir "public/js"
   :closure-defines {my.app.core/BASE_URL ""}

p-himik20:03:28

Yes. And that value, in turn, can be overridden via a CLI parameter, which can accept a real environment variable value.

šŸ™ 3
vanelsas14:03:01

Has anyone worked with https://github.com/recharts/recharts in Clojurescript/Reagent? Looking for a way to draw custom graphs. I looked at react-vis (it works) but it isn't maintained anymore. Can't find any examples with recharts.

macrobartfast18:03:35

if you try Oz and get the example project running, let me know the steps to get it runningā€¦

macrobartfast18:03:01

running into errors starting the project (due to my lack of knowledge, Iā€™m sure)

vanelsas07:04:06

I'll take a look thanks!

vanelsas06:04:20

thx! will take a look. At my first attempt I ran into all kinds of compiling issues. Hopefully your example can help me to get that right!

vanelsas07:04:20

Will do thanks!

macrobartfast18:03:50

very nice looking charts

macrobartfast18:03:17

(and Iā€™ll look at recharts)

macrobartfast18:03:43

I also am curious for an answer to your question (if anyone has looked at recharts in cljs) and and/or if there are other D3 type integrations for cljs.

macrobartfast18:03:16

I looked around and it seemed like there were a couple options that werenā€™t too current (but maybe they just still work).

macrobartfast18:03:30

recharts looks really nice.

Stuart19:03:21

I'm trying to learn re-frame and having a bit of issue with the basics. I have a little hello, world style app that lets me increment / decrement some numbers. Then when I click Start I want it to show the selected number and make the selector part dissappear: I have this for my selector bit:

(defn countdown-initiator []
  (let [time-entered (reagent.core/atom 0)
        visible @(rf/subscribe [:initiator-visible])]
    (fn []
      [:div.initiator {:style {:visibility (if visible :visible :hidden)}} ;; <<< I don't understand why this isn't triggering it to be invisible.
       [:div.timer @time-entered]
       [:div
        [:button.btn.up
         {:on-click #(swap! time-entered inc)}
         [:i.fas.fa-chevron-up]]
        [:button.btn.down
         {:on-click #(if (> @time-entered 0)
                       (swap! time-entered dec))}
         [:i.fas.fa-chevron-down]]]
       [:div
        [:button.btn.btn-danger {:on-click #(rf/dispatch [:start @time-entered]) ;; <<< On Clicking start, fire the :start event (I've put this below)
                                 :style    {:margin-top 10}} "Start"]]])))
My event that is changing :initiator-visible in my appdb and subscription:
(rf/reg-sub
 :initiator-visible
 (fn [db _]
   (db :initiator-visible)))

(rf/reg-event-db
  :start
  (fn [db [_ time]]
    (-> db 
        (assoc :time-remaining time)
        (assoc :countdown-visible true)
        (assoc :initiator-visible false)))) ;; << Set initiator-visible to false.
Re-Frame-10x shows the value appdb is false. Can someone see what I'm doing wrong? If I make a change to the code and it causes a hot-reload, it dissapears, so it's like I'm a step behind or something?

Stuart19:03:34

OK, have it working. Rather than doing

(let [visible @(rf/subscribe [:initiator-visible])]
    ,,,
    {style {:visibility (if visible ,,,)}})
I do
(let [visible (rf/subscribe [:initiator-visible])]
    ,,,
    {style {:visibility (if @visible ,,,)}})
And de-ref in the form-2 render function, it works but I'm not sure if this is the correct thing to do

Stuart19:03:04

I guess the de-ref has to happen in the render to make re-frame realise that render function needs re-run ???

manutter5119:03:53

Yes, thatā€™s it exactly.

manutter5119:03:44

You can also put the @(rf/subscribe [:initiator-visible]) inside your rendering function and skip the let completely.

Stuart19:03:23

Ah ok, I thought if had a re-agent form that had state I should use this let and fn to make it a form-2

Stuart19:03:14

btw, re-frame-10x is wonderful for debugging as a beginner in this framework!

manutter5119:03:29

Originally that was the idea, but re-frame now has a caching scheme for subscriptions that makes it work correctly if you throw the @(subscribe ,,,) directly in a form-1

manutter5119:03:41

Simplifies things a bit

Stuart19:03:52

cool, thank you! I didn't know that.

manutter5119:03:56

And yeah, 10x is great šŸ˜„

Kira McLean20:03:49

How are people writing big cljs apps testing them? Any open source examples out there? Iā€™m curious what people have found works well. Some things I want/need for my cljs test suite: ā€¢ easy to run (either a keyboard shortcut to run them in a repl, like I do for clj, or a watcher I can spin up that will auto-run any tests that change) ā€¢ runner for CI (could be the same way the tests run in development but doesnā€™t have to be, but either way need a way to run a single command and get an exit code indicating test suite pass/fail) I guess thatā€™s really all. Iā€™ve cobbled together some things from random blog posts and docs, but so far everythingā€™s still very janky. Iā€™m trying to fix this and find a way to develop a large cljs project thatā€™s not painful to test, so curious about othersā€™ experiences.

simongray20:03:14

@kiraemclean I just use the built-in reactive test runner in shadow-cljs and always have a tab open with my tests. When the favicon turns the wrong colour I go and check which test is failing.

Kira McLean20:03:02

that sounds pretty ideal.. what do you mean by ā€œbuilt-inā€ to shadow-cljs? the browser tests as described here? https://shadow-cljs.github.io/docs/UsersGuide.html#target-browser-test

Ronny Li21:03:24

that's exactly the guide that I followed

Ronny Li21:03:44

then npx shadow-cljs watch test to start the test in another tab.

simongray07:04:39

Yes. It's really easy to get going and works very well.

šŸ‘ 3
Kira McLean20:03:16

and do you run the tests in ci?

Heather21:03:13

Our clojurescript tests are all integration tests; we donā€™t have any unit cljs tests.

Kira McLean21:03:36

do you mean using etoain against a server running your whole app?

Heather23:03:04

We have an acceptance version of our app up on the web and we use selenium tests. Our clojurescript is all webpage/js code, so we have the tests click around there.

šŸ‘ 3
Ronny Li21:03:08

Hi everyone, what's the CLJS equivalent for the following:

let alpacaUrl = new URL('');
alpacaUrl.searchParams.set('response_type', 'code');
alpacaUrl.searchParams.set('state', state);
I'm mostly getting tripped up by repeatedly running alpacaUrl.searchParams.set to modify the original alpacaUrl inplace. (In my actual code I'm calling set on searchParams 6-7 times)

dpsutton21:03:52

(let [url (js/URL. "")]
  (doseq [[k v] [["response_type" "code"]
                 ["state" "state"]]]
    (.. url -searchParams (set k v)))
  url)
#object[URL ]

šŸ™ 3
p-himik21:03:18

And if you need to set only two parameters, then use doto instead of doseq.

lilactown22:03:10

yeah imo this is slightly more idiomatic:

(let [alpaca (doto (js/URL. "")
                (.. url -searchParams (set "response_type" "code")
                (.. url -searchParams (set "state" "state"))]
  ,,,)

šŸ™ 3
dpsutton22:03:27

(doto (js/URL. "")
              (.. -searchParams (set "response_type" "code"))
              (.. -searchParams (set "state" "state")))
(the url needs to be omitted in the doto)`. And that's fine for 2 but they mentioned it goes a bit higher to 6 or 7

šŸŽÆ 3
šŸ™ 3
Azzurite23:03:31

is there something special I have to watch out for when using macros in cljc? I created a macro and used it in the same file, however shadow-cljs tells me

31 | (def-styled-component  page [contents]
--------^-----------------------------------------------------------------------
 Can't take value of macro azzurite.web.content.homepage/def-styled-component
--------------------------------------------------------------------------------
does that need the code or is there just something I'm missing from the start?

Azzurite23:03:40

looks to me like I'm not "taking the value" but actually using the macro

lilactown23:03:27

@azzurite is this a CLJC file?

lilactown23:03:40

whoops skimmed your message sorry

lilactown23:03:16

in your namespace, you'll want to require-macros the macro namespace in a reader conditional

Azzurite14:04:13

why would I want to require the same namespace that the macro and the place where I use the macro are both in?

Azzurite14:04:43

> I created a macro and used it in the same file

lilactown14:04:02

it's a quirk of the compiler. there are two namespaces: your ClojureScript namespace, and the Clojure macro namespace

lilactown14:04:47

even though your Clojure namespace is loaded in the process of the compiler, it doesn't know to include its context in the compilation process of your ClojureScript namespace unless you declare it

Azzurite14:04:17

thank you very much! šŸ˜„

mfikes21:04:30

Even though you can use .cljc to try to put everything in one file, I've found it simple enough just to have two files. TBH, macros aren't being authored that frequently anyway. Here is what I do: https://blog.fikesfarm.com/posts/2018-08-12-two-file-clojurescript-namespace-pattern.html

mfikes21:04:14

I've even gone down the rathole of trying to actually define macros in the same file, using them just like you might in Clojure (even in the same REPL session): https://github.com/mfikes/chivorcam

mfikes21:04:27

But, IMHO, the two-file pattern is just simpler. šŸ™‚

lilactown23:03:55

(ns azzurite.web.content.homepage
  ,,,
  #?(:cljs (:require-macros [azzurite.web.content.homepage])))

,,,

šŸ‘† 3
lilactown23:03:40

I think that if you :refer [def-styled-component] you can use them without namespace qualifying them too