I've been looking into Zustand and Recoil -- two state management libraries that are relatively new.
Recoil is heavily advertised as being "very performant" for React apps with deeply-nested structures. However, I don't see how (or how exactly) it can be superior to Zustand performance-wise (concurrent mode aside).
I could've gotten it wrong, but here's how I understood it from articles and talks: The main reason "why" Recoil is performant is that any updates you make only trigger the relevant components to re-render, without bothering any other components. Recoil allows for it by design and out of the box, whereas Context-based libraries have to pass every change through the whole tree, have those changes diff'ed/reconciled and then probably only re-render what has to be changed.
Now, Zustand does not use the Context API at all. So, I would assume that (concurrent mode aside), it would have comparable performance benefits as Recoil, where Zustand would only "touch" the relevant components without ever piping the changes through the whole component tree.
Please let me know if I'm off in my understanding. Are these two libraries comparable in performance (without concurrent mode)? Or is there some other inherent property of Recoil's paradigm with atoms which makes it theoretically superior in terms of performance?
Please note: I would like the answer NOT to be influenced by patterns and practices too much. I understand that sometimes the biggest benefit of a paradigm can be in the "sound patterns it enforces", but I'm interested not in what they enforce but in what they allow to do with comparable effort. For example, I understand that a flat, normalized state will allow for better performance in Zustand, and that Zustand does not necessarily "force you to do it in a proper/scalable way". But I wouldn't want the "optionality" of the right patterns to be a disadvantage.
react-redux
in its connection to React. You provide a selector and it diffs the result against the current result, if they are different (reference comparison) it triggers an update. This appears to have the same issue asreact-redux
where if the state updates even if a component does not require a rerender it is still going to run the selector and do the diff to check if it needs to update. You can see this here. I did not look at Recoil. – Tachylyte