Offline Support

The React Native Chat SDK provides offline support (opt-in). Users can access and interact with chat when the network is unavailable.

Integration with Expo is possible using the expo-dev-client library. Offline support cannot be used in the "Expo Go" app, because it requires custom native code.

Best Practices

  • Enable offline support early in app startup to populate local state.
  • Don’t block UI on connectUser; render and let the client sync.
  • Reset the offline database on sign-out to avoid cross-user data leaks.
  • Keep queued actions minimal and surface retry states in the UI.
  • Replace ImageComponent with a caching implementation for reliable offline media.

Offline Support V2

In 7.1.0+, offline support moved into the StreamChat client for better performance and ergonomics.

The full list of changes is here. If you use offline support, upgrade to this version. No migration steps are required; just update the SDK and ensure stream-chat >= 9.2.0 if installed separately.

Features

The offline storage implementation currently offers the following features:

  • Access to chat when Internet connection is disabled or low.
  • Faster startup times and loading, since initial data is loaded from offline storage before performing any network requests.
  • Syncing of the offline database using WebSocket events and Sync API.
  • Optimistic offline updates during actions (send message, add reaction, etc.)
  • Queueing certain actions for retry after reconnect

The following features are currently NOT implemented. They will be implemented gradually as part of future releases.

  • Access to threads in offline mode.

Enabling Offline Support

To enable offline support:

Add @op-engineering/op-sqlite dependency

Check the version compatibility table to ensure your @op-engineering/op-sqlite version matches your stream-chat-react-native version.

yarn add @op-engineering/op-sqlite
  npx pod-install

Do not wait for connectUser call to succeed

Call connectUser before rendering chat components, but do not wait for it to resolve. This ensures:

  • Chat components have access to current user information, which is important to store/access offline data.
  • In case of slow or no network access, Chat components will still load the chat data without waiting for connectUser to succeed.
const chatClient = StreamChat.getInstance("API_KEY");
const App = () => {
  const [isClientReady, setIsClientReady] = useState(false);

  useEffect(() => {
    const startChat = async () => {
      const connectPromise = chatClient.connectUser(user, tokenOrTokenProvider);
      setIsClientReady(true); // this allows components to render
      await connectPromise;
      // Any other post-connectUser logic you may have goes here.
    };
    startChat();
  }, []);

  if (!isClientReady) return null; // or some loading indicator;

  return (
    <Chat client={chatClient} enableOfflineSupport>
      ...
    </Chat>
  );
};

Add enableOfflineSupport prop on Chat component

import { Chat } from "stream-chat-react-native";

<Chat client={chatClient} enableOfflineSupport>
  ...
</Chat>;

Reset the database on sign-out

Since the SDK doesn't handle app-level authentication logic, it's the application's responsibility to ensure the database is reset when a user gets logged out. This should generally be done before you call client.disconnectUser().

// Sign out logic (recommended approach for v8+)
await chatClient.offlineDb.resetDB();
await chatClient.disconnectUser();

Since version 7.1.0, the offline support API has been moved to the low level client. The legacy SqliteClient.resetDB() approach still works but using chatClient.offlineDb.resetDB() is the recommended approach.

Events Recovery

When the app is backgrounded or offline, other users may perform actions.

The SDK fetches and processes events since your last online session when you foreground the app.

No extra work required.

Queued Offline Actions

If the device loses connection during an action (send, react, delete), it fails initially but is retried automatically after reconnect.

Queued actions persist across app restarts and OS kills. Actions queued while fully offline also work.

These are the actions that support offline queuing:

  • Send message (version 7.1.0 and above)
  • Delete message
  • Add reaction
  • Delete reaction
  • Create draft (version 8.0.0 and above)
  • Delete draft (version 8.0.0 and above)

How To Cache Images

Available since version 5.3.0.

The SDK uses React Native's default image caching, which can be unreliable offline. You can replace all internal Image usage via the ImageComponent prop on Chat with a caching-enabled component that matches the Image API.

There are plenty of libraries available for this purpose:

Due to technical limitations, viewing images in full screen (image viewer) in offline mode is not currently supported.

Example using react-native-fast-image:

import FastImage from "react-native-fast-image";

...

<Chat
  client={chatClient}
  enableOfflineSupport
  ImageComponent={FastImage}
/>