Seb βš›οΈ ThisWeekInReact.com Profile picture
πŸ”₯ Join 40k devs - Stay up-to-date with React: β€’ πŸ“¨ https://t.co/DvLGHeLY5G β€’ @ThisWeekInReact β€’ @docusaurus maintainer β€’ πŸ‡«πŸ‡·

Sep 6, 2022, 13 tweets

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.

Keep scrolling