There are 16 hooks in React π π
And I bet you never used this one: useSyncExternalStore()
Used internally in state management libs, like Redux
But have you ever thought about using it in your own app code?
π‘ It could be useful & even prevent some React re-renders
π π§΅
Let's start with a real-world problem.
Imagine you are using React-Router and call useLocation() in a few places
β‘οΈ do some conditional rendering depending on pathname, hash, ?search query-string...
There are a few potential performance problems, for example:
- whenever you click on hash link, components reading only pathname will re-render β‘οΈ useless
- whenever you update the ?search querystring link, components reading only pathname or hash will re-render β‘οΈ useless
In practice, useless React re-renders might not be a problem
But still, in some cases, it can inadvertently ruin your whole app performances by triggering full page re-renders at the top of a complex tree.
β‘οΈ Can't we do better by default?
Enter useSyncExternalStore()
The official doc doesn't make it very clear π
You'll find a much better example on the new beta doc site here:
beta.reactjs.org/learn/you-mighβ¦
π‘ It turns out that the browser history can also be considered as an external data source.
React-Router (v5) provides us with everything we need to create a custom useHistorySelector() hook
The implementation is quite simple:
Now, when you click on a hash link above, the CurrentPathname component will not re-render anymore!
Using useSyncExternalStore() enables you to create your own selector system, returning only what you need to read in the React component
This prevents useless React re-renders!
There are so many external data sources that we can subscribe to, and implementing your own selector system on top might enable you to optimize React re-renders.
For example, let's consider we want to read the scrollY position of a page
We can implement this custom React hook:
Scroll the page and see how the components above re-render?
One re-renders much less!
π‘ Returning a narrower value also prevents useless React re-renders
Another interesting case of narrowing:
β‘οΈ useIsLargeScreen() > useResponsiveBreakpoint() > useViewportWidth() π’
I hope I convinced you to take a look at useSyncExternalStore()
IMHO this hook is underused & deserves a bit more attention
If you aren't on React 18 yet, check the use-sync-external-store shim
Also the with-selector export in case you need to return a memoized object
πππ This Week In React is back! π₯³π₯³π₯³
π οΈLet me introduce you to a new series of interactive articles
(Yes, I am a bit tired of just sending out a list of curated React links π
I can do more)
This thread is a sample of the very first article:
thisweekinreact.com/articles/useSyβ¦
β€οΈοΈIf you liked the thread, I'd appreciate a retweet π
Subscribe now!
π¨ Don't miss the next React article π€
thisweekinreact.com/revue
Share this Scrolly Tale with your friends.
A Scrolly Tale is a new way to read Twitter threads with a more visually immersive experience.
Discover more beautiful Scrolly Tales like this.
