Fork me on GitHub
#clojurescript
<
2020-06-07
>
J04:06:03

cljs doesn't seem to have <!! and >!!, is that right?

dpsutton05:06:44

Correct. Cljs cannot block while waiting for the take.

👍 4
tio09:06:29

I’m going through one of the tutorials and don’t understand why in the code snippet below you need the txt as in argument to the function inside of let in order for state change to work. When I print out the value of txt, I get nil; so I am confused what its purpose is.

(defn home-page []
  (let [state (reagent/atom 0)]
    (fn [txt]
      [:div
       (println txt)
       [:h1 {:style {:color (when txt "green")}} "Hello!"]
       [:p "This is my message."]
       [:button.green
        {:on-click #(swap! state inc)}
        (str txt " " @state)]])))

tio09:06:49

I am specifically referring to the line (fn [txt]

tio09:06:53

Any help is appreciated 🙂

thheller09:06:27

(defn home-page [txt] ... needs to match the (fn [txt] ... args. for the first invocation the arguments are first passed to home-page and reagent will then call the inner function with the same args. on update only the inner function is called.

tio09:06:47

I get unused binding txtclj-kondo from my text editor

tio09:06:59

But the result is the same regardless. The function it prints nil as the value on each iteration; however, the UI display the correct value.

borkdude09:06:48

@tiotolstoy You can prefix the outer unused arg with _ to make clj-kondo ignore it

borkdude09:06:27

so:

(defn home-page [_txt] (fn [txt] ...))

tio09:06:15

Fixed. Thank you!!

thheller09:06:43

@tiotolstoy how are you calling it? [home-page "hello world"] should have txt as "hello world"

tio09:06:54

a route points to the function

tio09:06:22

It’s the button with the 0 on init; on each iteration it increases the number.

tio09:06:29

Nothing needs to be passed in.

borkdude09:06:47

(those are not my words btw 😉)

tio09:06:00

I read that. I’m not sure I understand why you need it in the inner function since state is held in let line.

tio09:06:10

When I print, txt is always nil.

borkdude09:06:35

@tiotolstoy there are two kinds of information that are used in a component: arguments and data from reactive atoms. both make the component change when the data changes.

borkdude09:06:09

but if you use no args, then the only way to re-render is via reactive atoms

borkdude09:06:19

roughly speaking

tio09:06:22

OK; going to mull on this some more. Still very confused.

tio09:06:31

My confusion lies in that if you print txt you always get nil.

tio09:06:38

Despite the function working as expected. That’s all.

borkdude09:06:12

txt is an argument you pass in when calling the function.

tio09:06:24

Correct.

borkdude09:06:50

so if you don't pass in the argument, or the arguments don't line up somehow in the form-2 component, nil is expected

tio09:06:45

So you’re saying that in my function above, it should be printing nil correct?

tio09:06:49

I’m doing something wrong?

borkdude09:06:21

yes, because home-page has no args: []

thheller09:06:58

@tiotolstoy you didn't answer HOW you are using it. [home-page] will have txt as nil.

tio09:06:27

I’m calling it from the router

(def router
  (reitit/router
   [["/" :index]
    ["/items"
     ["" :items]
     ["/:item-id" :item]]
    ["/about" :about]]))

tio09:06:46

(defn page-for [route]
  (case route
    :index #'home-page
    :about #'about-page
    :items #'items-page
    :item #'item-page))

thheller09:06:08

yes. the router does not pass any arguments to home-page

tio09:06:03

I understand that.

tio09:06:19

However; when I remove the args; the state change does not work; despite txt not being used.

tio09:06:23

That’s where my confusion lies.

tio09:06:47

I’m just wondering what function txt serves as no args are being passed in; and yet I can’t do away with it.

tio09:06:53

Sorry if I’m not explaining myself well.

tio09:06:48

OK; nvm, when I remove it, it works fine. Thank you! It was a small bug on my part.

flyboarder17:06:28

So I am looking at this function thinking it might be better as a reduce?

flyboarder17:06:40

(defn set-in [m [k & ks] v]
  (doto m (obj/set k (if (empty? ks) v (set-in (obj/get m k #js{}) ks v))))

p-himik17:06:53

I think so. But better yet - I would go straight to cljs-bean or cljs-oops for this.

flyboarder17:06:29

@U2FRKM4TW looking to avoid additional external dependencies

p-himik17:06:17

Just in case that's because of the bundle size - cljs-oops should be fine since it's just a collection of macros.

lilactown17:06:11

since you're mutating it you can use getValueByKeys I think?

(defn set-in [o ks v]
  (obj/set
   (obj/getValueByKeys (to-array (drop-last ks))
   (last ks)
   v)
  o)

lilactown17:06:56

the downside here is that it traverses ks twice and there's some unnecessary allocation of seqs but

lilactown17:06:44

it's a bit more straight forward. you could probably write a helper fn to give you the last element w/ one traversal

lilactown18:06:41

(defn split-last
 ([xs] (split-last #js [] xs))
 ([arr [x & xs]]
  (if (seq xs)
    (recur (doto arr (.push x))
           xs)
    #js [arr x])))

flyboarder23:06:23

@lilactown thanks thats helpful