This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-10-21
Channels
- # 100-days-of-code (5)
- # announcements (6)
- # beginners (92)
- # cider (39)
- # cljdoc (35)
- # cljsrn (1)
- # clojure (187)
- # clojure-sanfrancisco (2)
- # clojure-spec (26)
- # clojure-sweden (2)
- # clojure-uk (1)
- # clojurescript (27)
- # cursive (19)
- # datascript (3)
- # datomic (19)
- # defnpodcast (1)
- # emacs (11)
- # fulcro (71)
- # incanter (1)
- # lein-figwheel (4)
- # lumo (10)
- # off-topic (19)
- # planck (5)
- # reagent (49)
- # reitit (2)
- # shadow-cljs (25)
- # spacemacs (1)
- # sql (1)
- # unrepl (4)
- # yada (4)
How can I got about checking for the component type of children in reagent? For example
(defn my-comp [props & children]
(into [:div ] children))
What I would like to do is map over children and see the type
of components passed in. For example, in vanilla React one would do
children.map((child) => child.type === SomeComp)
(defn my-comp [props & children]
(into [:div]
(for [child children]
; do whatever with child
)))
Perhaps I am missing something. If we do the above, child, for example, will look like this:
[#object[G__39155] {...props map content here}]
How can I tell the type of the component?Right, so it does appear to work when you run the following
(def child [#object[G__39155] {...props map content here}])
(= child some-comp)
How can I go about digging into #object[G__39155]
to see it a little clearer?I guess you’re doing adapt-react-class
to some existing react components? And that’s why you see hiccup-like vector there as child
?
No, I do not believe I am calling adapt-react-class
explicitly anywhere
You can check as-element
and as-component
in reagent.core to turn reagent vectors back to ‘real’ React components.
The code looks like this
(defn my-comp [props & children]
(into
[:div ]
(for [child children]
(do
(println child) ;; each child will print something like this: [#object[G__39155] {...props map content here}]
child))))
[my-comp {} [my-comp-2]]
This is not my strong area so I don’t know what’s the ‘correct’ way to check component type
These are 100% reagent components. No interop.
can i ask what you’re actually trying to accomplish? reagent has another layer of indirection in it because you construct the hiccup at runtime, which often allows for a more “reagenty” solution
Ok, cool. I’ve never needed to check for component type myself. Would it make sense to pass that information as props instead?
the reality is that the react components don’t really exist yet because you’re still at the hiccup phase
The goal is I have a compoent. Its going to have children. Based on the type of child. I need to modify the childs prop map dynamically.
if you’re going to be passed a bunch of hiccup, then just look at the first symbol in each vector
e.g., if you’re going to invoke this component like so: [my-parent-component [mychild1 ...] [mychild2 ...]]
, then my-parent-component
could just look at the symbols mychild1
and mychild2
Thats what I was hoping to do. But when I js/console.log
or println
each child I get #object[G__39155
instead of the symbol I would be expecting
so you actually do get passed a reagent component. i think you should be able to get the underlying react component. let me see if there’s an api for that
i always think that the parents get instantiated first, but that’s not right, unless i’m confusing myself
when you print the object to the console, do you have devtools installed? if not, you’re going to see the internal representation of the cljs vector
this renders “div”:
(defn parent [child]
[:div (first child)])
(defn app []
[parent [:div "hello"]])
I wonder if it is a devtools thing...that would be sad 😞
note, this technique will only work if your children are hiccup. in general, it is valid to pass a react element, so it wouldn’t work there
you could test whether it was a vector and act accordingly. to be totally general you’d have to mirror the ad-hoc polymorphic behavior of as-element
Any suggestions? As I mentioned, the goal is that I am building a very simple base component. Something like
(defn link
[props & children]
(into [:a ] children))
link
is going to accept props like :size
and allow i
tags in it.
[link {:size :medium } [:i] "I am a link"]
When the link is :medium
it has a different font-size. I would like the i
to match that font size. So I need the i
to know its supposed to be set to :medium
size.
Now, I could just have the developer manually set :medium
on the [:i]
tag, but really, if this is the way it should behave every time, I figure it would be nice to have this as the default behavior. Of course I will provide the ability to escape from this behaviourThats one of the other options I was exploring. I just wanted to do my due diligence and see how the technique above would work out.
it’s a little gross in reagent because of the extra layer of hiccup, but if you know you are getting hiccup, you can definitely do it
Alright, I had an opportunity to try this out and the issue is that when you have an HTML structure like this:
<button class="btn-class"> <i/> "button text"</button>
And the apply CSS as follows:
.btn-class i { ... }
The above will work. However, if the user needs to overwrite the .btn-styles i
styles for the i
component, they will not be able to because the specificity of .btn-class i
will win out over the custom class they add to the i
I do want their font-styles to win. As much as I would love to say that .btn-class i { ... }
is how everything should look, design will come up with a scenario where this is not true in 5% of the cases
it seems like if you were doing this by checking types that would have the same effect (?)
The way I was going to implement is something like this
[icon {:size :medium }]
Where icon would have a default set of sizes (`:medium` :large
). These turn into corresponding .small
.large
classes. So what the type check would do is:
1. is the component an icon?
yes? does it have a `size` prop defined? no? Inherit size from the `button` component.
no? ignore
So the user is still in control of the size and if they wanted to take it a step further and apply their own styles to the icon, we provide a :class
overwrite which can be used