This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-05-07
Channels
- # announcements (32)
- # asami (1)
- # babashka (127)
- # beginners (135)
- # bristol-clojurians (1)
- # calva (21)
- # chlorine-clover (5)
- # cider (2)
- # clara (9)
- # clj-kondo (24)
- # cljsrn (2)
- # clojure (25)
- # clojure-australia (4)
- # clojure-europe (135)
- # clojure-nl (8)
- # clojure-russia (3)
- # clojure-spec (4)
- # clojure-uk (9)
- # clojurescript (55)
- # cursive (6)
- # datomic (62)
- # events (1)
- # fulcro (1)
- # helix (19)
- # jobs (3)
- # jobs-rus (1)
- # kaocha (8)
- # malli (6)
- # meander (3)
- # off-topic (2)
- # pathom (3)
- # podcasts-discuss (1)
- # polylith (3)
- # practicalli (3)
- # re-frame (4)
- # reitit (5)
- # remote-jobs (1)
- # reveal (1)
- # rewrite-clj (9)
- # ring-swagger (1)
- # shadow-cljs (59)
- # xtdb (4)
https://github.com/ptaoussanis/timbre also really good
When working with Reagent + Google Maps API, I've created a "Polyline" form 2 component, saving a reference of the shape (google.maps.Polyline) in an atom within the component. When Figwheel re-renders after a change, the lines disapear on the Map, but I can confirm they still exist. Does anyone have any advice for working with shapes in google maps w/ Reagent? I want to generate Polylines for each item in an array stored in my global app state. I want to then select one of them and have it styled slightly differently (stroke color).
I think this has something to do with defonce
, since I'm storing state in a component w/ let
, it is lost when Fighweel reloads. I need to figure out a way to retain a reference to each shape drawn on the map that will persist.
(defn polyline
"Creates a Polyline on the Map"
[path gmap]
(let [ref (r/atom nil)]
(fn [_ _ is-selected]
; if the polyline hasn't been created, create it
(when (nil? @ref)
(reset! ref (js/google.maps.Polyline.
(clj->js {:path path
:geodesic true
:strokeColor "black"
:strokeWeight 6
:map gmap})))
)
; if the polyline has been created and toggled
; set the appropriate strokeColor
(when (some? @ref)
(if (and is-selected (some? @ref))
(.setOptions @ref (clj->js {:strokeColor "blue"}))
(.setOptions @ref (clj->js {:strokeColor "black"})))
)
nil
)))
In my App component, we iterate over each item that would render a Polyline:
(doall (for [activity (:activities @app-state)]
^{:key (util/get-activity-time activity)}
[maptools/activity
activity
(:gmap @app-state)
(util/is-selected? (:selected-activity @app-state) activity)
]))]]))
How are you rendering the google map? Does that happen inside or outside React render tree? My guess is that on figwheel reload your whole google map gets initialised again
Yeah, I think that's the issue as well. I have a component for the Google Map, which looks like this:
(defn google-map [app-state set-error]
(let [api-key (subs (-> js/document .-location .-search) 1)
center (clj->js {"lat" 40.730610
"lng" -73.935242})
loader (google.maps.plugins.loader.Loader.
(clj->js {:apiKey api-key
:version "weekly"}))]
(fn []
(.addEventListener
js/window
"DOMContentLoaded"
(-> (.load loader)
(.then (fn []
(swap! app-state assoc :gmap (google.maps.Map.
(. js/document (getElementById "map"))
(clj->js
{:center center
:zoom 8
:fullscreenControl false
:clickableIcons false
:disableDoubleClickZoom true})))))
(.catch #(set-error "Unable to load Google Maps"))))
[:div {:id "map"}])))
I can confirm that it re-renders each time I save a change in the project directory.
Yep. Google Maps is highly stateful and dealing with stateful js components is a bit painful. However this strategy has worked for me well https://github.com/day8/re-frame/blob/master/docs/Using-Stateful-JS-Components.md
Are there any alternatives to lumo which could support nodejs libraries?
shadow-cljs? https://shadow-cljs.github.io/docs/UsersGuide.html#node-repl https://shadow-cljs.github.io/docs/UsersGuide.html#target-node
Vanilla CLJS can. So Shadow-CLJS / FIgwheel-main too: • https://figwheel.org/docs/nodejs.html • https://clojurescript.org/guides/quick-start#running-clojurescript-on-node.js
I'm looking for something that I can embedded in AWS Lambda runtime.
@U05224H0W I would like to have the same capabilities as lumo
for Clojurescript or ts-node
for Typescript. I would like to just pack Clojurescript sources and node_modules in zip and run shadow-cljs bootstrapped-run entrypoint.cljs instead of compiling Clojurescript-> Javascript beforehand.
I don't know what you mean by "same capabilities". why use bootstrapped if you can just precompile it normally?
For AWS Lambda it's convenient to have a bootstrapped Clojurescript, so you could change sources and see immediate change on Lambda.
Dymanic import import('foo').then(module => console.log(module));
seems now supported by the last Google Closure compiler:
https://github.com/google/closure-compiler/issues/2770#issuecomment-834744931
Thanks. Rather, I saw the use to import another file dynamically like in these examples: https://inertiajs.com/pages#default-layouts But hey, this goes a bit against namespaces so I don't think so...
At the moment, the only solution I have found is to list the pages manually: https://github.com/prestancedesign/reagent-inertia-reitit-integrant-fullstack/blob/main/front/src/reagent/inertia.cljs#L112-L121
the dynamic+dynamic import style isn't supported by the closure-compiler and likely will never be, webpack also has issues with it.
so import(someVariable).then ...
will always be a problem for bundlers when they are supposed to bundle stuff
it is fine to do at runtime when you don't expect the bundler to bundler stuff but instead import already bundled stuff like code-split modules
I had an example for truly dynamic import here https://clojureverse.org/t/generating-es-modules-browser-deno/6116
webpack has a partial interpreter to figure out some dynamic imports but it is fairly limited and usually requires a bunch of build configuration
@U05224H0W Your example tackles truly dynamic imports whereas cljs.loader/load
requires for the imported thing to be a predefined module.
Are there some other differences that are important?
you'd use the dynamic-import instead of cljs.loader (in case of an :esm
build). so no cljs.loader included at all, just purely build-in import
the import variant that can be rewritten I have not tried yet. not sure what the closure-compiler turns it into or how it needs to be configured
Thanks both for these replies and useful informations...very interresting. 👍
Is it something interresting for CLJS in the futur?
I’m having an issue with eval
in Clojurescript. My use case is that I’m importing a bunch of rules as s-expressions and executing them against the current state of the app. I have a function called present?
that is kind of like (complement nil?)
but for JS input fields, i.e. it checks to see if a field’s value is ""
or js/NaN
, that kind of thing. When I eval
(present? 1)
, I get true. When I eval (or (present? 1))
, I get true. When I eval (or (present? 1) true)
I get nil
.
Here is a gist with the minimal steps to get there: https://gist.github.com/joshuamiller/20773273a234948013358f91e74c0392
Does anyone have any ideas what I might be doing wrong?
Just as an idea - you can try supplying a custom logging js-eval
to see what actually gets evaluated. Maybe it it will shed some light.
Good idea, I’ll give that a shot.
My or
with branches seems to not be returning anything, here’s the source it generates:
var or__43529__auto___44 = cljs.js.get_fn( 97 ).call(null,(1));
if(cljs.core.truth_(or__43529__auto___44)){
} else {
}
Ok, taking any of my stuff out of it, it seems like something is not right:
(eval (empty-state) '(or 1 2 3) {:eval js-eval*} :value)
results in nil
and the source it generates is
var or__43739__auto___26 = (1);
if(cljs.core.truth_(or__43739__auto___26)){
} else {
var or__43739__auto___27__$1 = (2);
if(cljs.core.truth_(or__43739__auto___27__$1)){
} else {
}
}
Looking at the docs for eval
, I figured it out (kind of). It takes an option :context
that defaults to :statement
. I need to use :expr
. I’m a little unclear on what each of these does, but it generates the correct code and works.
A statement is something purely imperative - it has no value. An expression is anything that has a value. In CLJ(S) world, everything is an expression. In JS world, sometimes something has to be a statement to work.
That makes sense in retrospect. I have played around with the code each context generates and you can see the difference.
At the same time, it's interesting how (present? 1)
still returns a value when using :statement
.
I guess that when it’s not embedded in a conditional, it doesn’t matter whether it’s side-effecting or whatever, so it just calls it and you get what JS gives you.
Yeah, but it should not have a return
there if it's a statement. Otherwise, it could break some things.
But I've never dealt with eval
before, so I can be completely wrong.
Ok, taking any of my stuff out of it, it seems like something is not right:
(eval (empty-state) '(or 1 2 3) {:eval js-eval*} :value)
results in nil
and the source it generates is
var or__43739__auto___26 = (1);
if(cljs.core.truth_(or__43739__auto___26)){
} else {
var or__43739__auto___27__$1 = (2);
if(cljs.core.truth_(or__43739__auto___27__$1)){
} else {
}
}
Looking at the docs for eval
, I figured it out (kind of). It takes an option :context
that defaults to :statement
. I need to use :expr
. I’m a little unclear on what each of these does, but it generates the correct code and works.