@jpsoares106 you'd have to add a :display-name
to your component, so the error/warning message can display it, reagent doesn't automatically add one. I haven't found a way to add :display-name
without using Form-3 components, so probably you want to wrap the Form-3 component setup with a macro where you can default to putting the var name as the :display-name
, if :display-name
is not explicitly passed in.
Reagent should set displayName to the name of the function: https://github.com/reagent-project/reagent/blob/master/src/reagent/impl/component.cljs#L289, though if you use form-2 components, I'm not sure if it uses parent or inner fn name.
(it uses the parent fn name)
@juhoteperi huh, I see. How sure are you about this? I haven't seen :display-name being set ever automatically I think, unless I explicitly set it in a Form-3 component, but I might very well be wrong about that and just missed it or only actually looked when doing Form-2 (not dismissing it's possible, just don't think I've seen it myself, if I remember correctly)
There are tests for this, and if you look at Reagent app using React dev tools components tree, all components use the function names
But there could be cases where stacktraces don't contain the names. This might be affected by Reagent calling render in requestAnimationFrame or something. Or if the error is from event handler.
yeah, you're absolutely right, sorry about that!
https://github.com/reagent-project/reagent/issues/382 this issue looks related. Example cases where errors don't mention source fn name would be helpful, though I can probably find some cases myself.
If a reagent component re-renders does it re-render everything including child components? Or does it only re-render the parent component?
I am adding printlns in the render functions of the child components and I am noticing that they are being fired even though the inputs to the component have not changed. Could it be that the function runs but does not actually do any dom changes so in reality its not actually 're-rendering' but just running the render function?
yes, it will potentially re-render all of the child components. there are three levels of optimizations happening:
• reagent will do some best-effort check to see if any of your components props have changed. this will be if the arguments you pass are =
to the last arguments. e.g. [my-component 1 2]
will always render with the same args, so as long as it’s parent isn’t re-mounted it will not be called again.
• React will do some best-effort attempt to see if the React elements returned by your component are identical?
, which is usually not the case even if you’re returning the same hiccup
• React will diff the VDOM elements created with what was last rendered, compute the minimal amount of changes to the page to reflect the latest UI tree
Ah, okay so if the parent component is re-mounted due to some state changes then the children will re-render again?
yes, if it’s re-mounted. if it’s re-rendered, it should do a check to see if the arguments are different
there’s another complication when a component conditionally renders some stuff. e.g.
(defn c1 []
(let [count (r/state 0)]
(fn []
[:div
[:button {:on-click #(swap! count inc)} "+"]
[number-component count])])))
(defn c2 []
(let [count (r/state 0)]
(fn []
[:div
[:button {:on-click #(swap! count inc)} "+"]
(if (even? count)
[even-component count]
[odd-component count])])))
in this case, numper-component
should only mount once. each render of c1
will trigger a re-render, but if for some reason c1
changed without changing the count
atom, number-component
should be memoized and not be called again.
c2
will re-mount evens
and odds
every time because the component tree changes from render to render.So if a component that dereferences state, has the state changed like (swap! state identity)
will that trigger a re-render right?
Nope it did not