Hi, I am using reagent with functional compiler with re-frame , and when using a subscribe all the elements re-render, even thought the value itself didn't change. Imagine a selection, where every item decides if it is the one selected. Only two items should re-render, the one swapping to true, and the one swapping to false. Unfortunately when using subscribe it re-renders all children. Any ideas?
Example code, re-rendering all components, based on react profiler
(def x (atom 1))
(defn something-inner [value]
[:div (str value)])
(defn something [selected-number]
[:<>
(map
(fn [a] ^{:key a}[something-inner (= selected-number a)])
(range 10))])
(defn view []
(let [selected-number x]
[:div
[something @selected-number]
[:div {:on-click #(reset! x (rand-int 10))}
"Choose number"]]))Should you be using an r/atom?
What Mike said, but also if you want local state in a component you should probably keep it in that let block and use a form-2 component as described https://github.com/reagent-project/reagent/blob/a14faba55e373000f8f93edfcfce0d1222f7e71a/doc/CreatingReagentComponents.md#form-2--a-function-returning-a-function.
Also I see no calls to subscribe in your code.
I found the solution. Yes I tried it multiple ways. [:<>] fragment is at fault. Believe or not, if I change the fragment to a [:div] around the map it works as expected.
And it's not just for the subscribe It's also r/atom and (react/useState)
Might be related: https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-mostly-complete-guide-to-react-rendering-behavior/#standard-render-behavior