Fork me on GitHub
#clojurescript
<
2021-10-28
>
JB Seo00:10:05

Reagent's reagent.core/children does not support functional component now. As reagent.core/current-component returns mocking object, I write a helper function like below:

(defn get-children [^js this]
  (if (.-props this)
    (reagent.core/children this)
    (when-some [v (.-argv this)]
      (reagent.impl.component/extract-children v))))
Can I safely use it for functional component? for example
(defmacro nest-children []
  `(some->> (reagent.core/current-component)
            (get-children)
            (into [:<>])))

(defn fn-comp [{:keys [prop1]}]
  [:div
   (str "Prop1 is " prop1)
   (nest-children)])

(defn demo []
  [:f> fn-comp
   {:prop1 "hello"}
   [:span "world"]
   [:span "foo"]
   [:span "bar"]])
It seems work for simple tests.

p-himik08:10:06

You might get better answers in #reagent But also, I wouldn't use a macro for that, it's an unnecessary complication.

JB Seo13:10:07

Thanks. I want to avoid macro, too. however, nest-children doesn't work when I turn it to a function.

p-himik13:10:48

Did you remove that backtick upon turning it into a function?

roelof06:10:52

sorry for asking so much but why does my degree tag get not updated when I choose a output type. Code so far : https://github.com/RoelofWobben/clojure-temp-converter

roelof06:10:28

oke this seems to work

(defn update-output [_]
  (gdom/setTextContent degree get-output-temp))
but now the new degree is added to degree here instead of changing things

roelof06:10:59

<h3 id="convertedUnit">F</h3>

roelof06:10:26

I changed also this : (def degree (gdom/getElement "convertedUnit"))

roelof07:10:30

Never mind , got it working with

(defn update-output [_]
    (gdom/setTextContent degree (get-output-temp))) 
`

thheller06:10:04

its just "change" there not "on-change"

roelof06:10:33

thanks, I changed it but still nothing changes

thheller07:10:39

as always ... verify what you think you are working with. hint (input-target) is incorrect

Quentin Le Guennec09:10:04

Hello, clojurescript expects me to quote dest-ns in (ns publics dest-ns) line 3, which is kind of complicated to do:

(defmacro export-library-cljc! [dest-ns exclude-symbols]
  `(do
     ~@(for [[intern-name] (ns-publics dest-ns)]
         (when-not (contains? exclude-symbols (symbol (str intern-name)))
           `(do
              ~(when (contains? (ns-interns 'clojure.core) (symbol (str intern-name)))
                 `(ns-unmap *ns* (symbol ~(str intern-name))))
              ~`(defalias ~(symbol (str dest-ns "/" intern-name))))))))
The macro is working perfectly in clojure, can someone explain?

p-himik09:10:18

Clojure 1.10.0
user=> (doc ns-publics)
-------------------------
clojure.core/ns-publics
([ns])
  Returns a map of the public intern mappings for the namespace.
but
ClojureScript 1.10.879
cljs.user=> (doc ns-publics)
-------------------------
cljs.core/ns-publics
([quoted-ns])
Macro
  Returns a map of the public intern mappings for the namespace.
In CLJ, it's a function. In CLJS, it's a macro. Why exactly this difference exists, I don't know. Probably due to how some things in CLJS simply don't exist in run time, like vars.

Quentin Le Guennec09:10:47

Oh, I see. Which means it'll be already quoted in clojure but not in clojurescript.

p-himik09:10:55

Your conclusion is the other way around - it will be quoted in CLJS since it's a macro. Fortunately for your implementation, the CLJ version of ns-publics also accepts a symbol. So you can just use a symbol there at all times. Might still be tricky given that one is an fn and the other is a macro.

Quentin Le Guennec09:10:10

Yeah, quite tricky

roelof11:10:05

again a question about react keys I see now this error :

template.cljs:413 Warning: Every element in a seq should have a unique :key: ([learn_cljs.weather.temperature {:label "Today", :value nil}] [learn_cljs.weather.temperature {:label "Tomorrow", :value nil}])
 (in )

roelof11:10:09

Can I solve this with this :

^{key 'today'}{:label "Today", :value nil}]
if not, please give me the right answer . This is bugging me for several days

p-himik11:10:09

Have you gone through the links I provided before? One of them was with an example from the Reagent's website.

roelof11:10:16

but that one was not given a example of how to add a key before a {}

p-himik11:10:47

I don't understand what you mean. Why would you need to add it in front of {}?

p-himik11:10:09

The warning clearly mentions

([learn_cljs.weather.temperature {:label "Today", :value nil}]
 [learn_cljs.weather.temperature {:label "Tomorrow", :value nil}])

p-himik11:10:22

It talks about a seq, and that above is that seq.

p-himik11:10:48

It talks about every element in the seq, and an element of that seq would be each Hiccup vector.

roelof11:10:11

Then Im confused

roelof11:10:54

I did it here

(defn title []
  [:h1 (:title @app-state)])

(defn temperature [temp]
  [:div {:class "temperature"}
   [:div {:class "value"}
    (:value temp)]
   [:h2 (:label temp)]])

(defn postal-code []
  [:div {:class "postal-code"}
   [:h3 "Enter your postal code"]
   [:input {:type "text"
            :placeholder "Postal Code"
            :value (:postal-code @app-state)
            :on-change #(swap! app-state assoc :postal-code (-> % .-target .-value))}]
   [:button {:on-click get-coordinates} "Go" ]])

(defn app []
  [:div {:class "app"}
   [title]
   [:div {:class "temperatures"}
    (for [temp (vals (:temperatures @app-state))]
      ^ {key [temperature temp]}[temperature temp])]
   [postal-code]])

roelof11:10:43

the part that the error message is talking about looks like this

(defonce app-state (r/atom {:title "WhichWeather"
                            :latitude 0
                            :longitude 0
                            :postal-code ""
                            :temperatures {:today {:label "Today"
                                                   :value nil}
                                           :tomorrow {:label "Tomorrow"
                                                      :value nil}}}))

p-himik11:10:18

In your code, that seq above is generated with this code:

(for [temp (vals (:temperatures @app-state))]
  [temperature temp])
A key in React represents an identifier for an element within its parent element - unique within the scope of that parent. It needs to remain stable, it can't be just the index. In your case, such a stable identifier seems to simply be the key in the :temperatures map. Here's a solution for your particular case:
(for [[temp-id temp] (:temperatures @app-state)]
  ^{:key temp-id}
   [temperature temp])

p-himik11:10:21

But given that: • Maps are inherently unordered • You just have two items in that map here's how I'd rewrite it:

(let [{:keys [today tomorrow]} (:temperatures @app-state)]
  [temperature today]
  [temperature tomorrow])
The code doesn't even need :key anymore.

p-himik11:10:05

> the part that the error message is talking about looks like this The error you posted in the main channel clearly doesn't talk about that defonce at all. Why do you think the definition of your app-state is relevant here?

roelof11:10:04

oke, so that key instead of the for loop

roelof11:10:14

that code is given by the book

roelof11:10:04

I think it is relevant because it pointing to that code label: Today : value nil

p-himik11:10:06

That's just the value of temp. It doesn't talk about your actual code, it only talks about the value it receives. It's a run-time warning, not a compile-time one - it doesn't check your code, it only checks the values.

p-himik11:10:20

> that code is given by the book Right. Not a great look for that book TBH.

roelof11:10:20

I know. we discussed that earlier

roelof11:10:33

I tried that key thing but still the same runtime error

roelof11:10:42

(defn app []
  [:div {:class "app"}
   [title]
   [:div {:class "temperatures"}
    (for [temp (vals (:temperatures @app-state))]
      ^ {key  temp}[temperature temp])]
   [postal-code]])

p-himik11:10:33

What you wrote is completely different from what I wrote.

p-himik11:10:55

:key is not the same as key. temp is not the same as an identifying value.

p-himik11:10:49

Use my code. Confirm that it results on no warnings. Then go through the React documentation on keys while keeping my code in mind, along with the fact that ^{:key x} in front of a Hiccup vector results in assigning a React key to the resulting React element. BTW that ^{...} construct just assigns metadata. So ^{...} [...] is sugar for (with-meta [...] {...}). And Reagent uses :key metadata to assign keys to React elements.

roelof11:10:13

so this instead of the for loop

(let [{:keys [today tomorrow]} (:temperatures @app-state)]
  [temperature today]
  [temperature tomorrow])

roelof12:10:01

hmm, this breaks the layout

(defn app []
  [:div {:class "app"}
   [title]
   [:div {:class "temperatures"}
    (let [{:keys [today tomorrow]} (:temperatures @app-state)]
  [temperature today]
  [temperature tomorrow])]
   [postal-code]])

p-himik12:10:05

No, I meant the loop, given that it's the only one of the two code examples I provided that still needs the :key.

p-himik12:10:48

The layout breakage is surprising, given that the resulting markup should be exactly the same.

roelof12:10:39

I did use the loop and that one works perfect without any error messages

roelof12:10:06

maybe I have to find a better book/tutorial to learn clojurescript

p-himik12:10:49

The ClojureScript website has a selection of materials: https://clojurescript.org/community/resources

roelof16:10:42

I do not see why mu right blue area is not updated here : https://github.com/RoelofWobben/clojure-temp-converter