@lilactown This was a nice overview of how things work in different CLJS React wrappers.
One extra trick I’ve used when using the #js {:cljs-props …} passed to my own components is to memoize that JS object; that way the objects are
(identical? o1 o2)
=> true
between renders (unless the :cljs-props data changes) which prevents extra re-rendering
are you doing that using React.memo
, or some other way?
Like that, just via CLJS memoize https://github.com/raspasov/alexandria-clj/blob/main/src/ax/react/core.cljs#L65 Additionally, I do use React.memo on all components, since I try to render only via props in most cases; Technically, using (memoize …) naively is a memory leak but it hasn’t caused problems for me for a very long time; Ideally, some sort of a caching elimination strategy can be used.
Using React.memo here https://github.com/raspasov/alexandria-clj/blob/main/src/ax/react/core.cljc#L4
I am not sure if I can achieve the same effect of avoiding re-renders on the same props data just via React.memo… I haven’t tried.
I believe React.memo checks for the JS equivalent of (identical? …) objects, if I remember correct; I can perhaps supply a custom comparison function via CLJS (= …) to React.memo and avoid (memoize …) https://reactjs.org/docs/react-api.html#reactmemo
that's right
IME over-memoizing can be a problem. A lot of React components construct data during render that gets passed in as props to other components; doing a deep equality check on this data every render can have non-negligible performance penalties
especially if the data is similar shape and changes most of the time, it's the worst of all worlds: you do the deep equality check for comparison and then re-render anyway!
that's the rationale behind helix following what React does: no memoizing by default, then you can easily opt in to doing identical?
, and if needed you can opt in further to other equality checks e.g. using =
If a data changes really often (like multiple times per second), I actually opt for using local state/hooks so I can isolate the re-render only to one specific component rather than rendering from the root… It does make a difference in performance for the better.
But I do that very sparingly, only for performance reasons; that way most of the application stays “pure” and renders via props (easy to reason about) and only a few most perf. critical components that get updated very often get to re-render via local state/hooks.