Fork me on GitHub
#reagent
<
2018-05-08
>
Macroz08:05:11

what's your solution for autocomplete component these days? sometimes I use material-ui but what if I don't want to depend on it?

Macroz10:05:47

thanks, maybe it doesn't have "chips" kind of functionality? So that you can easily remove items by clicking

nenadalm10:05:08

it doesn't look like from the demo.

Macroz10:05:11

yes or the docs

Macroz10:05:08

I think some SEO would be useful for this one

troglotit08:05:20

Hey! How do I do

[:div
  (if x?
    [[:div]
     [:div]]
    [[:span]
     [:span]])]
without additional divs?

👍 4
juhoteperi11:05:50

Or just list: [:div (list [:div] [:div]), works the same as sequences (`for`, map) so you'll need to add React keys

juhoteperi11:05:08

Fragments are needed when you want to return multiple events from component directly

juhoteperi11:05:42

(defn foo [] (list [:div] [:div])) doesn't work, but (defn bar [] [:<> [:div] [:div])) works

juhoteperi11:05:05

Also, you could use into: (into [:div] (if x? [[:div] [:div]] [[:span] [:span]])) might be simplest, definitely no need to use React keys in this case as this is effectively same as writing [:div [:div] [:div]]

troglotit12:05:15

tried to use (list ..) - caught exception TypeError: Cannot convert a Symbol value to a string

troglotit12:05:32

wanted to reproduce it in simple example - could not reproduce.

troglotit12:05:16

so yeah, still using fragments - doesn’t seem that inapproriate

juhoteperi11:05:22

Reminder: Fragments are for cases where one wants to return multiple elements from a component: https://reactjs.org/docs/fragments.html

juhoteperi11:05:17

Inside components, you can use into, list, for, map

andrea.crotti14:05:42

I never quite understood how reagent handles the differences between [:div (gen-html :one)] and [:div [gen-html :one]]

andrea.crotti14:05:04

so from my understanding the behave the same way, and it's simply done to delay the evaluation (I guess)

andrea.crotti14:05:23

but in many cases it also behaves in the same way

andrea.crotti14:05:57

and can it be nested anyway? would [:div [transform [gen-html :one] :two]] make sense as well?

andrea.crotti14:05:29

what's the lower level function to call to just see what gets generated in the REPL?

mikerod14:05:38

If you use vectors (square brackets) instead of lists (parentheses), then it is interpreted as a hiccup form. If the hiccup has a symbol as first element, then that symbol’s associated fn will be used as the render fn for the component.

mikerod14:05:20

However, since you used a vector, Reagent can avoid calling the fn until it needs to. If the arguments haven’t changed in value, then it won’t be called - that sort of optimizatoin

mikerod14:05:49

If you use a list form, with parentheses, then it will be called naturally because Reagent isn’t done with macros, so evaluation order is the same as any other Clojure code

mikerod14:05:14

In that case, Reagent never gets the opportunity to step in and avoid the render fn call to avoid the nested hiccup generation

mikerod14:05:28

I’ve said some of this in pretty simplified terms, but that’s the basic idea.

andrea.crotti14:05:13

ok yes thanks, I was digging for some code that actually can render the HTML directly without writing into the DOM

andrea.crotti14:05:32

and I think it's this function?

(defn as-element [x]
  (cond (js-val? x) x
        (vector? x) (vec-to-elem x)
        (seq? x) (if (dev?)
                   (expand-seq-check x)
                   (expand-seq x))
        (named? x) (name x)
        (satisfies? IPrintWithWriter x) (pr-str x)
        :else x))

mikerod14:05:24

as-element is probably a good place to look

mikerod14:05:22

If you are just trying to look at how things interact at that level.

mikerod14:05:38

as-element > vec-to-elem > reag-element for something like [my-fn <blah>]

mikerod14:05:14

But you probably have to also understand reagent.impl.component/as-class a bit (which is called in reag-element, to understand the mechanism that the vector hiccup forms may avoid calling the render fn

mikerod14:05:50

Your component fn, say my-fn above, is used to generate a React style class that implements various life cycle methods for you.

mikerod14:05:55

In reag-element, you’ll notice it calls (react/createElement c jsprops). This treats the hiccup form as a React element, and therefore goes through those life cycle methods. If you called it without hiccup, with a list/parentheses, it would have just called your fn as a normal fn with no potential to avoid recomputing the nested renders.

andrea.crotti14:05:19

nice thanks for the explanation

👍 4
justinlee16:05:08

the simpler version of the rule is: no brackets, no component

4
mikerod17:05:55

Yep, I was just dumping the details since I thought that there was interest in that particular question. Your phrase nicely captures the idea.

justinlee17:05:54

oh yea, there’s enough magic to reagent i think it is really helpful to understand how it works.

justinlee17:05:03

there are still things I don’t get, like how reagent caches the react component. it looks like it stores the react component on the actual hiccup datastructure or something like that, but i can’t figure it out for the life of me (not without a debugger)

mikerod17:05:21

@lee.justin.m Yeah, I have found going through the impl to be a useful exercise

mikerod17:05:57

To cache the component class on a reagent tag where the symbol is just a function, I thought it just sticks the cached version on a keyword on the underlying JS function object

justinlee17:05:49

oh maybe it’s storing it on the function object not the data from the function.

mikerod17:05:04

yeah, I think it directly associates things as new props on the fn object

mikerod17:05:16

that was my understanding at least

mikerod17:05:47

I actually am more familiar with clj than cljs and to me it seems crazy to be able to randomly add props to fn objects

mikerod17:05:59

but from the JS-world, I get it

justinlee17:05:39

right, now i remember. it does this completely insane thing where it sets the function on a property of itself:

(if (reagent-class? f)
    (cache-react-class f f)
    (let [spec (meta f)
          withrender (assoc spec :reagent-render f)
          res (create-class withrender)]
      (cache-react-class f res))

justinlee17:05:45

that is diabolical

mikerod17:05:15

Yes, it is a pretty twisted flow to follow

mikerod17:05:43

I don’t immediately know why it needs to do that either

mikerod17:05:53

that seems to be the “cache hit” path. not sure why it needs to ensure it is cached.

mikerod17:05:22

well, nevermind it isn’t the hit path

mikerod17:05:31

I mean, it’s a fn that has had the component build and set on it before

mikerod17:05:13

idk though, I’d have to dig through that whole path again to remember things enough. hah

dusteh18:05:46

Hello, I'm new to reagent and had a question about how it handles react template syntax {{key : "val"}} can I just drop the outer {} or is there some other syntactic sugar I should use?

dusteh18:05:54

Thank you!