Hacker News new | ask | show | jobs
by codeflo 1551 days ago
Two thoughts.

One, you don’t rely on a semantic guarantee if you use useMemo for derived state. Avoiding rerendering counts as an optimization as far as the React docs are concerned (your program works if there’s an extra render), and this is in fact exactly what it was intended for. The docs you linked seem to agree: Regardless of whether an offscreen component keeps or doesn’t keep its useMemo, the code is correct and there’s at most one extra render.

Second, while I agree with the verbosity complaint, I personally make a point to use useMemo as coarsely as possible. It’s often completely fine to compute all derived state in a single big lambda that returns one big (immediately destructured) object. It’s only when you have multiple pieces of derived state that update individually and are also all expensive to compute that you actually need fine-grained useMemo calls. And in this case, you can always think about extracting sone of that logic into a helper function/hook.

It’s not perfect, but I think it’s possible to avoid a lot of the pain most of the time.

1 comments

I'm with you on thought #2. Regarding your first thought, however: if you want control over when `useEffect` callbacks fire, identity isn't just an optimization, it's a necessity. For example (used in another comment): if you're not using a smart intermediate layer like `react-query`, you can unintentionally trigger loading states and re-fetches if you're not closely watching dependency array identities
I'm curious if you've used useDeepCompareEffect, the use-deep-compare-effect npm package? I've found that it is pretty reasonable foolproofing for many of these identity questions. I'm well aware of Dan Abramov's objections to the deep equality checking [1] but I still find it a bit easier for me and other devs to reason about when doing things like data fetching.

[1] https://twitter.com/dan_abramov/status/1104414469629898754

Hadn't heard of that -- thanks for sharing!

Crazy how many choices there are in the mix (use-deep-compare-effect, the `JSON.stringify` approach mentioned by Dan, `useMemo`, and `useMemoOne`). Feels like a "pick your poison" scenario, as each one has a significant issue.

That being said, `useDeepCompareEffect` does seem the most "foolproof", and "foolproof" is probably more important than intuitive or performant in most cases.

Oh, that’s a good example. I’ll argue that you should try to use primitives (strings/numbers) as keys in those cases. But if you can’t, then you’re right that identity is critically important.