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 ?
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.
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
thanks for that insight, if I understand correctly,
(goog-define BASE_URL "<http://localhost:8080/api>")
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 "<https://fully-qualified-domain-name/api>"}
Yes. And that value, in turn, can be overridden via a CLI parameter, which can accept a real environment variable value.
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.
I'll take a look thanks!
I use recharts here https://github.com/lipas-liikuntapaikat/lipas/blob/master/webapp/src/cljs/lipas/ui/charts.cljs
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!
take a look at https://github.com/metasoarous/oz
Will do thanks!
very nice looking charts
(and I’ll look at recharts)
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.
I looked around and it seemed like there were a couple options that weren’t too current (but maybe they just still work).
recharts looks really nice.
if you try Oz and get the example project running, let me know the steps to get it running…
running into errors starting the project (due to my lack of knowledge, I’m sure)
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?Have a gist of the full page https://gist.github.com/stuartstein777/a1e9e40146489392cca4af97b7bfb23d
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 doI guess the de-ref has to happen in the render to make re-frame realise that render function needs re-run ???
Yes, that’s it exactly.
You can also put the @(rf/subscribe [:initiator-visible])
inside your rendering function and skip the let
completely.
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
btw, re-frame-10x is wonderful for debugging as a beginner in this framework!
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
Simplifies things a bit
cool, thank you! I didn't know that.
And yeah, 10x is great 😄
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.
@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.
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
Yes. It's really easy to get going and works very well.
and do you run the tests in ci?
Our clojurescript tests are all integration tests; we don’t have any unit cljs tests.
do you mean using etoain against a server running your whole app?
that's exactly the guide that I followed
then npx shadow-cljs watch test
to start the test in another tab.
Hi everyone, what's the CLJS equivalent for the following:
let alpacaUrl = new URL('<https://app.alpaca.markets/oauth/authorize>');
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)(let [url (js/URL. "<https://app.alpaca.markets/oauth/authorize>")]
(doseq [[k v] [["response_type" "code"]
["state" "state"]]]
(.. url -searchParams (set k v)))
url)
#object[URL <https://app.alpaca.markets/oauth/authorize?response_type=code&state=state>]
And if you need to set only two parameters, then use doto
instead of doseq
.
yeah imo this is slightly more idiomatic:
(let [alpaca (doto (js/URL. "<https://app.alpaca.markets/oauth/authorize>")
(.. url -searchParams (set "response_type" "code")
(.. url -searchParams (set "state" "state"))]
,,,)
(doto (js/URL. "<https://app.alpaca.markets/oauth/authorize>")
(.. -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 7is 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?looks to me like I'm not "taking the value" but actually using the macro
@azzurite is this a CLJC file?
whoops skimmed your message sorry
in your namespace, you'll want to require-macros
the macro namespace in a reader conditional
why would I want to require the same namespace that the macro and the place where I use the macro are both in?
> I created a macro and used it in the same file
it's a quirk of the compiler. there are two namespaces: your ClojureScript namespace, and the Clojure macro namespace
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
thank you very much! 😄
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
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
But, IMHO, the two-file pattern is just simpler. 🙂
(ns azzurite.web.content.homepage
,,,
#?(:cljs (:require-macros [azzurite.web.content.homepage])))
,,,
I think that if you :refer [def-styled-component]
you can use them without namespace qualifying them too
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.