Fork me on GitHub

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 => 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]
     [:div ] 
     (for [child children]
            (println child) ;; each child will print something like this:  [#object[G__39155] {...props map content here}]

[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


Are you doing interop with some existing React library?


Or are those components you’re defining yourself in reagent?


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


Sounds brittle to me.


yea, but checking the type of your children is brittle even in react


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


you’ve inherently got coupling between the parent and child


i forgot how reagent works for a second


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


arg sorry i confused myself


my first approach should work--you are being passed the hiccup


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


(there’s probably a better way to structure this whole endeavor, honestly)


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 behaviour


Why not use CSS?


Set a class on [:a] and then use selectors


Thats 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


but the C in CSS is really designed for just this kind of problem.


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


do you want their styles to win?


you’re only going to change the font size right?


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 (?)


god i loath css 🙂


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