This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-04-16
Channels
- # announcements (2)
- # asami (5)
- # babashka (52)
- # beginners (42)
- # biff (3)
- # cljdoc (4)
- # cljsrn (2)
- # clojure (30)
- # clojure-austin (35)
- # clojure-dev (3)
- # clojure-france (11)
- # clojurescript (36)
- # conjure (6)
- # cursive (5)
- # fulcro (33)
- # graalvm (41)
- # lsp (54)
- # malli (1)
- # music (2)
- # off-topic (7)
- # overtone (1)
- # pedestal (5)
- # polylith (2)
- # remote-jobs (1)
- # sci (28)
- # shadow-cljs (38)
- # vim (15)
- # web-security (1)
- # xtdb (8)
Happy Easter Clojurians! I hope some of you out there are online and interested in helping me out 🙂 I have this component:
(defn component [id]
(let [status (r/atom nil)
(debounced-api-call! status id)
(fn []
[:h1 (str "the result is: " @status)])))
I want the API to be called every time the prop id
changes.
Right now it only gets called once, when the component is rendered.Either create a form-3 component and make the check for a different id
in :component-did-change
or add a ratom, something like internal-id
, reset!
it to id
in the outer fn and check whether it's equal to the new id
in the inner fn.
Alternatively, don't do it in the component at all - do all the data related stuff where the data resides.
I’m attempting your second suggestion. Can you clarify how that would look in my example?
This doesn’t work:
(defn component [id]
(let [status (r/atom nil)
internal-id (r/atom id)
(fn []
(when (not= @internal-id id)
(reset! internal-id id)
(debounced-api-call! status id))
[:h1 (str "the result is: " @status)])))
Otherwise, the changes to id
never make it to the view function - the value from the outer scope gets closed over.
Why for some objects, say the name is *a
, when I type *a
in the console, it only shows
#object[Error Error: Network Error]
If I test with (js-keys *a)
, it shows the output:
#js ["config" "request" "response" "isAxiosError" "toJSON" "clojure$core$protocols$Datafiable$" "clojure$core$protocols$Datafiable$datafy$arity$1"]
However, for some other objects, typing them in the console, it will directly show in the
{"asdf":"asdf", "xxx":"yyy"}
format.when you print an object, cljs looks at the prototype of the object to see if it knows how to print it. e.g. for maps and vectors, it would print it like EDN.
if an object has the Object
prototype object, then it will print it by enumerating its keys and values.
if it doesn't find a prototype that it knows how to print, it just calls .toString
on it
it's easy to create an object that is an instance of Object
, e.g.
#js {:a 42}
;; => #js {:a 42}
(doto (Object.)
(goog.object/set "a" 42))
;; => #js {:a 42}
it sounds like your a*
isn't an instance of Object
, but something else. e.g. an axios request object created from a class
objects that are created from new SomeClass
have SomeClass
on their prototype, not object. so cljs doesn't know how to print them by default
That makes sense. But (js-keys) still has the ability to inspect the keys even if the object is of SomeClass.
For the above, (.-message e)
gives the error message. but (js-keys e) gives weird things like
#js ["clojure$core$protocols$Datafiable$" "clojure$core$protocols$Datafiable$datafy$arity$1"]
just testing this in the JS console
> let e = new Error("hi")
< undefined
> Object.keys(e)
< [] (0)
> Object.getOwnPropertyNames(e)
< ["message", "line", "column", "stack"] (4)
typically there's a reason that fields wouldn't be enumerable. tbh I do not know why these fields aren't on errors:thinking_face: it would be nice of CLJS protocol properties were non-enumerable, perhaps?
I have a general question on js introspection. How do you introspect a js object returned from an external library, it could be a normal js object, or it also be an instance of a class. Are you using Object.getOwnPropertyNames
in the repl to introspect. If so, isn’t that too many chars to type?
Given your other questions, you're probably asking about React Native specifically, because when it comes to browsers it's really easy - just output an object to the JS console or view it as a local when the execution is paused in the debugger. I have never had to deal with RN, but surely it has some similar or maybe even the same tools. This page does seem to suggest it: https://reactnative.dev/docs/debugging#debugging-on-a-device-with-chrome-developer-tools
What do you guys use to minify/inline static resources (like index.html, main.css etc.) in a tools.deps + shadow-cljs setup?
I guess a more general question is, how to build a packing pipeline (a la webpack) that can use arbitrary command-line tools, while monitoring all file changes in a folder?
In the past, some suggested using webpack along with shadow-cljs. Is that still the best practice?
Not sure what you mean by "minify/inline" when it comes to index.html
. Regarding reloading index.html
- safer and easier to just refresh the page.
Regarding CSS - you can make shadow-cljs reload it: https://shadow-cljs.github.io/docs/UsersGuide.html#_css_reloading
And you can use build hooks to minify it in production or compile SASS/SCSS/LESS into CSS or whatever else you might need.
And if you need something more complex, personally I find writing manual scripts for it (babashka or maybe even plain bash) much simpler and even easier than using webpack.