React 18 milestone: React-Redux adopts useSyncExternalStore

This is a sample from my This Week In React newsletter. Subscribe for more!

React-Redux v8 alpha.0 was just announced by Mark Erikson.

The library is now fully rewritten in TypeScript.

More importantly, React-Redux v8 is adopting a new React 18 hook useSyncExternalStore (replacing useMutableSource).

This hook allows React to work properly in concurrent mode and sync with an external state (from Redux) without tearing (the UI can’t become inconsistent with store state).

This hook is the “level 2” (make it right) of the state subscription ladder:


Dan Abramov explains it’s an important milestone for React 18:

For the first time we’ve been able to move the “meat” of the react-redux bindings implementation into react itself.
It wasn’t a lot of code, but it relied on a bunch of hacks and complexity that kept growing. Now that “meat” is 5 lines of code, we handle the rest.

import { useSyncExternalStoreExtra } from 'use-sync-external-store/extra';

// React-Redux v8 alpha code in useSelector()
const selectedState = useSyncExternalStoreExtra(
  // TODO Need a server-side snapshot here
Enter fullscreen mode

Exit fullscreen mode

To ease incremental adoption in libraries today, an external package use-sync-external-store has been published, allowing to use this hook with a consistent API on React 16, 17 & 18.

Unlike the former useMutableSource API, this new hook supports unstable, inline selectors without re-subscribing, and you won’t need to wrap selectors in useCallback to stabilize them:

// Not ideal
const user = useSelector(
  useCallback(state => state.user,[])

// Simpler
const user = useSelector(state => state.user)
Enter fullscreen mode

Exit fullscreen mode

The community remains very interested to have a native useContextSelector() hook in React core.

A performant useContextSelector() hook would allow Redux to try again passing the store state directly as context value, instead of passing a store object and managing subscriptions internally. React would now hold entirely the Redux state and the React-Redux bindings would move to the ladder’s stage 3 (make it fast). This stage would permit React to avoid unnecessary rendering work when a Redux store update happens while a concurrent rendering is in progress.

useContextSelector is still under research and is not a mandatory feature for React 18 to land. Andrew Clark commented that it will more likely be released in a minor 18.x release.


Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

GIPHY App Key not set. Please check settings

TweetCatcher — Twitter bookmarks on steroids

Scan, index, and archive all of your paper documents