React 18 milestone: React-Redux adopts useSyncExternalStore
Published: 2021-10-05 15:20:01

This is a **sample** from my [This Week In React](https://thisweekinreact.com) newsletter. **Subscribe for more!**

[![This Week In React newsletter banner](https://cdn.hashnode.com/res/hashnode/image/upload/v1633438809395/zNdSjKPIY.png)](https://thisweekinreact.com)

**Update**: you might also like my other article [useSyncExternalStore - The underrated React API](https://thisweekinreact.com/articles/useSyncExternalStore-the-underrated-react-api)

--- 

[React-Redux v8 alpha.0](https://github.com/reduxjs/react-redux/releases/tag/v8.0.0-alpha.0) was just  [announced by Mark Erikson](https://twitter.com/acemarke/status/1444736773142241285).

The library is now fully rewritten in TypeScript.

More importantly, React-Redux v8 is adopting a new React 18 hook [`useSyncExternalStore`](https://github.com/reactwg/react-18/discussions/86) (replacing `useMutableSource`).

This hook allows React to work properly in concurrent mode and sync with an external state (from Redux) without [tearing](https://github.com/reactwg/react-18/discussions/69) (the UI can't become inconsistent with store state).

This hook is the "level 2" (*make it right*) of the [state subscription ladder](https://github.com/reactwg/react-18/discussions/70):

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1633431540221/DWMU6Iwtc.png)

[Dan Abramov explains it's an important milestone for React 18](https://twitter.com/dan_abramov/status/1444742231513051138):

> 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.

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

// React-Redux v8 alpha code in useSelector()
const selectedState = useSyncExternalStoreExtra(
  store.subscribe, 
  store.getState, 
  // TODO Need a server-side snapshot here
  store.getState, 
  selector, 
  equalityFn
);
```

To ease incremental adoption in libraries today, an external package [`use-sync-external-store`](https://www.npmjs.com/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](https://github.com/reactwg/react-18/discussions/84) without re-subscribing, and you won't need to wrap selectors in `useCallback` to stabilize them:

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

// Simpler
const user = useSelector(state => state.user)
```

The community remains very interested to have a native [`useContextSelector()`](https://github.com/facebook/react/pull/20646) hook in React core. 

A performant `useContextSelector()` hook would allow Redux to [try again](https://github.com/reduxjs/react-redux/releases/tag/v7.0.1) 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](https://github.com/reactwg/react-18/discussions/70) (*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](https://github.com/reactwg/react-18/discussions/73) that it will more likely be released in a minor 18.x release.