What is useSyncExternalStore in React?

useSyncExternalStore is a built-in React hook introduced in React 18 that allows your components to subscribe to external data sources. This article explains why this hook is necessary for concurrent rendering, how its API works, and provides a practical example of how to implement it to keep your application state in sync with external stores or browser APIs.

In React 18, the introduction of concurrent rendering allowed React to pause and resume rendering to keep the main thread responsive. However, this introduced a problem called “tearing” when components read from external, mutable data stores (such as Redux, MobX, or global window variables) that change during rendering. Tearing occurs when different parts of the UI display inconsistent data for the same state. useSyncExternalStore solves this by forcing synchronous updates when the external store changes, ensuring UI consistency.

The API Syntax

The hook accepts three arguments and returns the current state of the store:

const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);

Practical Example: Subscribing to Browser Online Status

One of the most common use cases for useSyncExternalStore is subscribing to native browser APIs, such as the network online status (navigator.onLine).

import { useSyncExternalStore } from 'react';

function subscribe(callback) {
  window.addEventListener('online', callback);
  window.addEventListener('offline', callback);
  return () => {
    window.removeEventListener('online', callback);
    window.removeEventListener('offline', callback);
  };
}

function getSnapshot() {
  return navigator.onLine;
}

export function ChatStatus() {
  const isOnline = useSyncExternalStore(subscribe, getSnapshot);

  return (
    <div>
      <p>Your connection status: <strong>{isOnline ? 'Online' : 'Offline'}</strong></p>
    </div>
  );
}

In this example, the subscribe function listens for the browser’s online and offline events and triggers a re-render. The getSnapshot function returns the current boolean state of navigator.onLine.

When Should You Use It?

You should use useSyncExternalStore when: * You are building or maintaining third-party state management libraries (like Zustand or Redux) that manage state outside of React’s built-in state. * You need to subscribe to native browser APIs, such as window dimensions, geolocation, or connection status, that change over time.

You should not use it for: * Managing standard component state (use useState or useReducer instead). * Handling side effects that can be managed within the standard React lifecycle (use useEffect instead).