Fork me on GitHub
#clojurescript
<
2020-08-04
>
Chris McCormick02:08:14

this can be a handy snippet to have near the top of your project too: (defn $ [q] (.querySelectorAll js/document q))

6
gomosdg07:08:22

Hi, each time I save my code hot reload kicks in but I get this error:

error when calling lifecycle function wishlist-app.core/init Error: Target container is not a DOM element.
So it does not end up loading app but it does after pressing F5. This is my render function:
(defn render-active-panel []
  (rdom/render
   [site-layout]
   (.getElementById js/document "app")))
(defn init []
  (re-frame/dispatch-sync [:initialize-db])
  (hook-browser-navigation!)
  (render-active-panel))
;; shadow-cljs configuration
{:source-paths
 ["src/dev"
  "src/main"
  "src/test"]

 :dependencies
  [reagent/reagent "0.10.0"]
  [re-frame/re-frame "0.12.0"]
  [clj-commons/secretary "1.2.4"]]

 :builds
 {:app {:target     :browser
        :output-dir "resources/public/js"
        :asset-path "/js"
        :modules    {:main {:entries [wishlist-app.core]
                            :init-fn wishlist-app.core/init}}

        :devtools {:repl-init-ns cljs.user
                   :preloads     []
                   :http-port    8021
                   :http-root    "resources/public"
                   :after-load   wishlist-app.core/init
                   :autoreload   true}}}}
Feel like I am missing something and it might be something stupid.

thheller07:08:11

@lilokoego you should use :after-load wishlist-app.core/render-active-panel not init since that will re-initialize everything. https://code.thheller.com/blog/shadow-cljs/2019/08/25/hot-reload-in-clojurescript.html

thheller07:08:30

pretty sure your hook-browser-navigation! thing may reset the page and remove the <div id="app">

gomosdg07:08:55

Aaah! That makes sense! Thanks a lot!

mikethompson08:08:22

@lilokoego If you have any further issues, the re-frame-template will give you a working scaffold for a re-frame application, and that would act as a good reference.

gomosdg08:08:52

Thanks @mikethompson. I will set up a different project and see how everything is hooked.

Hobgoblin08:08:30

Hi, I'm porting existing React TSX code to CS and in TSX there is a pattern that you just import CSS files (like this: import './index.css';) which I guess just get run as a plain JS script inside the browser. The file in question just defines variables (like this: --ion-color-primary: #3880FF;). Is there a way for me to invoke the same code to be run from CS in the same way? I obviously tried to google for a solution but as of yet did not find one.

thheller08:08:53

it isn't turned into JS. webpack bundles up .css file references and just serves a regular .css file

thheller08:08:26

and no there is no way to express this in CLJS

Hobgoblin08:08:06

Ok. If that is the case now if I reference the file like typical CSS in HTML should that work? Like in Reagent terms [:link {:rel "stylesheet" :href "./index.css"}]

thheller08:08:07

no. the file is likely in some npm package and probably has multiple.

thheller08:08:24

or is this an actual css file you have? in that case yes you just include it normally in html (probably not reagent though)

Hobgoblin08:08:16

ok, I have both cases: a local file that is simple and then the complex stuff from imported libraries

Ambre08:08:42

Hi everyone, I'm working on a React-native / re-frame / re-natal / figwheel app, and I can't get anything to work: Be it with a running emulator or my actual android device, my app doesn't start but the major problem is that I never get any "easy to google/ find on stackoverflow" kind of error I should note that I am on linux (Ubuntu 20.04) and that my phone/emulator is on android Every time I want to start up the app, I do re-natal use-android-device [avd | real] ; re-natal use-figwheel and then in 3 different shells : lein figwheel android react-native start (the metro bundler) react-native run-android Sometimes I will get stuck on the "Waiting for figwheel to load files" screen, which is sometimes resolved with a adb -s <device-name> reverse tcp:8081 tcp:8081. If I get past that screen I might end up with a cryptic error message (on the phone) :

Doesn't support name: 
eval
    [native code]
<unknown>
    
tryCallOne
    
<unknown>
    StyleSheetValidation.js:60:5
_callTimer
    ReactNativeRenderer-dev.js:1750:6
_callImmediatesPass
    ReactNativeRenderer-dev.js:1795:13
callImmediates
    ReactNativeRenderer-dev.js:2320:21
callImmediates
    [native code]
__callImmediates
    
<unknown>
    
__guard
    index.js:42
flushedQueue
    
flushedQueue
    [native code]
invokeCallbackAndReturnFlushedQueue
    [native code]
I also want to point out that the error messages sometimes change without me doing anything differently, sometimes rebooting my computer makes the thing work, just for a while ; all-in-all, a very frustrating experience If anyone has a lead as to where I could find my salvation I would be forever thankful

zackteo11:08:36

Hi Everyone, honestly abit overwhelmed at the different pathways/frameworks I can use to build a web app with Clojurescript. I've been looking at Fulcro for abit but am wondering if it will be a right fit. Need to make a single page application with stuff like leaflet (gis library) and postgresql (for spatial queries) Any advice or suggestions would be appreciated! :D

danieroux11:08:32

Hi @zackteo https://github.com/Lokeh/helix may be more useful to your needs, if complex UI state management is not your primary concern. I’ve integrated leaflet, it’s straightforward enough, message me with questions on that if you want

zackteo11:08:28

@danie ooh, by any chance have you also tried integrating arcgis js api? https://developers.arcgis.com/javascript/. I'll probably still to leaflet but it might be a consideration. Hmmm I'm not too sure if the core of what I need to do is considered as complex state management. Will need to allow the end user to perhaps pick a series of choices (like locations) or filter out locations (choices computed by the backend) which will need user input to continue and save that state at any point to then load back to it later :thinking_face:

danieroux11:08:19

I’ll start with Helix, an an atom to keep that state (until it breaks down). And no, I’ve only ever done leaflet 🙂

zackteo11:08:05

So that first and if there's issues then reagent and reframe? :o

adamrenklint18:08:58

Anyone with experience and knowledge about how to use cljs.js that can help me? I’m trying to get the self-hosted compiler working, but am running into trouble with defn and all the other cljs.core macros not being expanded. The input CLJS

(ns foo.bar)
(def a 12)
(defn x [] (+ a 30))
(+ (x) 3)
becomes
goog.provide("foo.bar");
foo.bar.a = (12);
foo.bar.defn.call(null,foo.bar.x,cljs.core.PersistentVector.EMPTY,cljs.core._PLUS_.call(null,foo.bar.a,(30)));
cljs.core._PLUS_.call(null,foo.bar.x.call(null),(3));
and eval fails with Cannot read property 'call' of undefined . Before calling cljs.js/eval-str, I’ve loaded the analysis cache for both cljs.core and cljs.core$macros. The first I dumped to a file using dump-core, the second was copied from .cljs_node_repl. I then load those files into my browser app (which is built with Shadow CLJS) and call load-analysis-cache!. Any ideas of what to look at next would be helpful.

phronmophobic18:08:18

your example code seems to work for me. • what optimization level are you compiling the eval cljs code with? • what compiler options are you using?

phronmophobic18:08:31

here's the source I get:

goog.provide("foo.bar");
foo.bar.a = (12);
foo.bar.x = (function foo$bar$x(){
return (foo.bar.a + (30));
});
(foo.bar.x.call(null) + (3));

thheller18:08:59

you basically need to replicate what :target :bootstrap does which is kinda non-trivial. your case sounds like either the macros aren't compiled, loader or their analyzer data is missing.

cjsauer19:08:07

What might be the most efficient way to build up a very large string in cljs? At the moment I’m using numerous calls to str and it’s showing up in my profiler as a potential slowdown. I’m looking at goog.string/buildString as a potential alternative.

noisesmith19:08:28

one solution is to create a collection, and use concat or join as a final step

noisesmith19:08:22

or even that buildString which uses a single function over collection instead of a stateful object

thheller19:08:39

my guess would be that str is the most efficient. building a collection and then calling str to combine them all just sounds like doing everything twice.

thheller19:08:17

you can maybe hack something together using UInt8Array

noisesmith19:08:26

repeated calls to string are extremely inefficient

noisesmith19:08:14

eg. compare (apply str coll) (fast) with (reduce str coll) (slow) - in the second case it recreates the first part of the accumulator on every call

thheller19:08:41

hmm yeah maybe building a native array and then joining it is faster

noisesmith19:08:23

right, I should have thought of apply str though, that should already be doing the right thing

thheller19:08:14

depends on the coll I guess, gotta account for building that too

cjsauer20:08:41

Great advice. apply str is much faster than what I was attempting. Thank you 🙏

🍻 3
dvingo19:08:39

I'm attempting to add a reader literal that will work in cljs - I'm attempting to copy the setup in the time-literals library. I'm confused by the parsing code is a returning a list instead of a normal function: https://github.com/henryw374/time-literals/blob/master/src/time_literals/data_readers.cljc

noisesmith19:08:30

I would expect these functions to return lists, your reader functions aren't macros, they should execute the code that constructs your data

phronmophobic19:08:54

not sure what the data-readers namespace is doing, but check out

dvingo19:08:42

I'm attempting to register a tag parser but I'm getting my-type is not a valid ClojureScript constant.

phronmophobic19:08:49

do you have the code snippet?

dvingo19:08:44

yea, putting one together..

dvingo19:08:49

[2020-08-04 15:56:48.763 - WARNING] :shadow.cljs.devtools.server.worker.impl/cljs-compile-ex - {:input {:code "#time/offset \"nil PT10H\"", :ns dv.tick-util, :repl true}}
ExceptionInfo Failed to process REPL command {:eof? false, :ns dv.tick-util, :form #time/offset "nil PT10H", :source "#time/offset \"nil PT10H\"", :tag :shadow.cljs.repl/process-ex}
	shadow.cljs.repl/process-read-result (repl.clj:520)
	shadow.cljs.repl/process-read-result (repl.clj:494)
	shadow.cljs.repl/process-input (repl.clj:674)
	shadow.cljs.repl/process-input (repl.clj:658)
	shadow.cljs.devtools.server.worker.impl/eval17629/fn--17632 (impl.clj:755)
	clojure.lang.MultiFn.invoke (MultiFn.java:234)
	shadow.cljs.devtools.server.util/server-thread/fn--17258/fn--17259/fn--17267 (util.clj:285)
	shadow.cljs.devtools.server.util/server-thread/fn--17258/fn--17259 (util.clj:284)
	shadow.cljs.devtools.server.util/server-thread/fn--17258 (util.clj:257)
	java.lang.Thread.run (Thread.java:830)
Caused by:
Note: The following stack trace applies to the reader or compiler, your code was not executed.
ExceptionInfo failed compiling constant: dv.tick_util.Offset@6cf58528; dv.tick_util.Offset is not a valid ClojureScript constant. {:constant #time/offset "nil PT10H", :type dv.tick_util.Offset, :clojure.error/phase :compilation}
	cljs.compiler/fn--3260 (compiler.cljc:304)
	cljs.compiler/fn--3260 (compiler.cljc:301)
	clojure.lang.MultiFn.invoke (MultiFn.java:229)
	cljs.compiler/emit-constant-no-meta (compiler.cljc:283)
	cljs.compiler/emit-constant-no-meta (compiler.cljc:275)
	cljs.compiler/emit-constant (compiler.cljc:299)
	cljs.compiler/emit-constant (compiler.cljc:295)
	cljs.compiler/fn--3404 (compiler.cljc:611)
	cljs.compiler/fn--3404 (compiler.cljc:608)
	clojure.lang.MultiFn.invoke (MultiFn.java:229)
	cljs.compiler/emit (compiler.cljc:202)
	cljs.compiler/emit (compiler.cljc:182)
sending the form #time/offset "nil PT10H" in a clojurescript repl gives the above error

dvingo20:08:57

ok - so I think it's an issue with my data type and not with the reader - I replaced the body of the read-offset function to return 500 and that is now working

phronmophobic20:08:40

yea, I'm stumped as to what the issue is

phronmophobic20:08:36

> dv.tick_util.Offset@6cf58528 this makes me think there's some weird inter play where the source is being read on the jvm and then compiled to cljs/js

phronmophobic20:08:50

you might be able to write some cljs that doesn't go through shadow-cljs to see if that might be part of the problem.

dvingo20:08:21

hmm ok, yea that's a good idea, as I'm not sure how to narrow things down otherwise

dvingo20:08:31

thanks for taking a look

quoll22:08:01

Quick question… Are transient maps supposed to support find in ClojureScript? They do in Clojure. i.e. ClojureScript:

=> (def m (transient {}))
#'cljs.user/m
=> (def m (assoc! m :a 1))
#'cljs.user/m
=> (find m :a)
nil
=> (get m :a)
1
Clojure:
=> (def m (transient {}))
#'user/m
=> (def m (assoc! m :a 1))
#'user/m
=> (find m :a)
[:a 1]
=> (get m :a)
1

quoll22:08:12

Working around it by using the (get [o k not-found]) arity on get, but it took me a while to track down that this was my problem

noisesmith23:08:02

IMHO doing lookup on transients is often a sign you aren't using them as intended

noisesmith23:08:25

they are designed to be used during some accumulation step then finalized into a real coll

quoll23:08:29

it is an unusual thing, I grant you

quoll23:08:05

I’m doing it for a multimap

noisesmith23:08:15

also standard warning that transients are not a safe way to mutate a data structure in place

quoll23:08:27

but should find work?

noisesmith23:08:34

someone else needs to answer that, the number of tiny ways clojure/cljs differ and which percentage of differences are intentional but undocumented are beyond me, sorry