This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-03-19
Channels
- # bangalore-clj (2)
- # beginners (217)
- # boot (3)
- # cider (130)
- # cljs-dev (117)
- # cljsrn (11)
- # clojure (99)
- # clojure-china (1)
- # clojure-denver (1)
- # clojure-dev (22)
- # clojure-italy (30)
- # clojure-norway (5)
- # clojure-russia (13)
- # clojure-sanfrancisco (3)
- # clojure-spec (74)
- # clojure-uk (107)
- # clojurescript (40)
- # clr (6)
- # core-async (25)
- # core-logic (4)
- # cursive (1)
- # data-science (1)
- # datomic (62)
- # duct (11)
- # editors (14)
- # figwheel (3)
- # fulcro (12)
- # funcool (1)
- # garden (12)
- # graphql (19)
- # jobs (4)
- # jobs-rus (1)
- # lein-figwheel (1)
- # leiningen (12)
- # luminus (5)
- # off-topic (45)
- # onyx (12)
- # other-languages (1)
- # parinfer (5)
- # programming-beginners (3)
- # re-frame (113)
- # reagent (63)
- # remote-jobs (10)
- # ring-swagger (1)
- # shadow-cljs (31)
- # slack-help (3)
- # spacemacs (27)
- # specter (1)
- # unrepl (44)
- # yada (16)
Hello. Did anyone have a problem with advanced compilation of type-3 components?, I have now:
(defn my-component [...]
:componentDidMount (fn [...] (this-as this (.myMethod this)))
:myMethod (fn [...] ...do something...)
...)
And Google Closure Compiler (with options :pseudo-names
and :pretty-print
set to true
) reports me an error:
this.$myMethod$ is not a function
(i.e. JavaScript compiled by it reports)
@andrewboltachev I think the name created by create-class
won't be optimized, but the name from .myMethod
call will be optimized so this won't work
yeah, it seems like so
((gobj/get this "myMethod") ...)
might work
Or other similar ways to get the method dynamically from the object, so the name is not optmized
aha, and gobj
itself has to be :require
d?
aha. great, would try this!
thanks
It is the recommended way to access JS objects in Cljs
(Reagent implementation itself uses aget/aset
currently, but those should only be used with JS arrays...)
gotcha
Have suchlike problems accessing SVG objects as well: .getBBox
method gots compiled away
So, :advanced
definitely comeas at a cost
You can add this extern to the project to fix that: https://github.com/google/closure-compiler/blob/master/contrib/externs/svg.js
@juhoteperi great, should it go to src/externs
?
Path doesn't matter, you need to add it to :compiler-options :externs
list
aha, so then like :externs ["src/externs/svg.js"]
It should probably be packaged into Cljsjs, as extern only package, I though it was done already but doesn't seem like it
Is it possible via some trick to get the name of a parent component? e.g. in a React lifecycle method?
@andrewboltachev wait why are you doing it this way?
rather than like this https://github.com/reagent-project/reagent/blob/master/docs/CreatingReagentComponents.md#form-3-a-class-with-life-cycle-methods
:component-did-mount
receives this
as its first argument: http://blog.ducky.io/reagent-docs/0.6.0-alpha2/reagent.core.html#var-create-class
no need to mess with this-as
uhm, indeed, thanks for pointing out!
... I guess this has nothing to do with your question 🙂
Juho already answered the actual question
if you have externs inference on, you could also add a type annotation to the component. with shadow-cljs,
:component-will-mount (fn [^js this] (.mymethod this ...))
.getBBox
is special I imagine because more common DOM methods like .focus
are blacklisted in Google Closure and won't be minified (I think...)
@mhuebert interesting, does this work with cljsbuild or figwheel as well?
i don’t know, it would be worth trying. externs inference itself is not specific to shadow-cljs
however I think @thheller did quite a bit of work to make externs inference in shadow-cljs work (a) more often and (b) without extra config, so I am not sure how it compares to the cljsbuild experience
I use it all the time now though. ’tis easy to add ^js
in front of whatever thing should be treated as external, = few & easy to debug :advanced problems
the page you linked to doesn't mention ^js
hinting, only specifying a class like ^js/Foo.Bar
How does one go about specing a function in reagent which returns hiccup? I know these are just vectors, but I am curious if one would expect something more than :ret vector?
?
the first element must be a function or a keyword
@pesterhazy the ^js
hint without a class reference is specific to shadow-cljs. I feel the class should be optional and it doesn't matter anyways. see https://code.thheller.com/blog/shadow-cljs/2017/11/06/improved-externs-inference.html
@thheller interesting
I want to do an official proposal for this at some point but didn't get around to it yet
seems reasonable to me
anything that reduces the pain of adv compilation is a win in my book
does reagent provide anyway of making state available to helper functions? In React, you can simply call this.state
since its part of a class. In Reagent, I find myself passing state as an argument way too often since I don't want global variables.
@mcama200 whenever i find that i want to reach for a method, i replace it with a function defined in a let block
thanks for your help. would you have any examples I could see? So the bulk of your functionality would be defined in the let
statement?
yea that’s how I do it.
(defn my-comp
[args]
(let [state (reagent/atom nil)
method-1 (fn [] (swap! state ...))]
(fn [args]
[:div "whatever"])))
the let blocks can get huge but so can class definitions. the main reason why people don’t like this style is because you can’t test the functions individually
@mcama200 I pass my app-state ratom around as the first argument pretty much everywhere .. a great alternative is to use re-frame tho (it solves this headache)
yeah that was my understanding as well. Just wanted to see if Reagent provided any mechanism without reaching out to a data-management lib.
i’d say the “reagent” way is to use functions and closures. the design principle of the library seems very focused on enabling you to write websites using normal functions
@gadfly361 what is the basic re-frame solution in a nutshell?
@lee.justin.m basically re-frame closes over app-db implicitly, so when you write event handlers, you always have access to the entire world of state (so you don't have to pass it in as an argument anymore) .. it's just a convenience (that i think has more positive than negatives)
Also I guess saying closes over is kind of a lie .. i think app-db is injected as a coeffect, but basically works the same way
@lee.justin.m @gadfly361 if you want it in a nutshell read "What Are They?" in this doc. Just a few paragraphs: https://github.com/Day8/re-frame/blob/master/docs/Coeffects.md#what-are-they
At moments like this I point towards this re-frame FAQ entry: https://github.com/Day8/re-frame/blob/master/docs/FAQs/DoINeedReFrame.md