yarn add @op-engineering/op-sqlite
npx pod-install
Offline Support
React Native Chat SDK provides OOTB support for offline mode, which means user will be able to access and interact with chat even when the network is off. This is an opt-in feature that needs to be explicitly enabled on application level.
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.
Offline Support V2
In versions 7.1.0
and above we’ve refreshed the way our offline support works. It now lives in the StreamChat
client which provides a variety of benefits as well as quality of life improvements.
The full list of changes can be seen here. If you are using offline support we highly recommend that you get to this version. There are no migration steps to consider, all you have to do is upgrade your SDK to the specified version and make sure stream-chat
is at least version 9.2.0
if you have that installed.
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.
- Optimistically update offline database during chat interactions, such as send message, add reaction, etc.
- Queueing up of certain chat actions to be executed later if failed
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, please follow the given steps:
Add @op-engineering/op-sqlite
dependency
Contemplate our dependency version compatibility table to make sure your
@op-engineering/op-sqlite
version are compatible with yourstream-chat-react-native
version.
Do not wait for connectUser
call to succeed
It is important that you call the connectUser
method on the chat client, before you render Chat components. But you don’t need to wait for connectUser
to succeed before rendering Chat components. This is to ensure:
- 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 when signing out the user
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()
.
import { SqliteClient } from "stream-chat-react-native";
// Sign out logic
await SqliteClient.resetDB();
chatClient.disconnectUser();
Since version 7.1.0
, the entirety of the API for offline support has been moved to the low level client.
Even though the previous approach will still work, you might want to migrate early to the new way of doing this:
await chatClient.offlineDb.resetDB();
chatClient.disconnectUser();
Events Recovery
Whenever the app is not foregrounded and connected to the internet, there are likely other actions performed by other users. Especially in a Chat app, there are tons of events that can happen while you were offline.
To overcome this situation, we are fetching all the events that happened since the end of your last online session up until the moment you foreground the app, we are processing them and making sure the app accordingly reflects those.
This happens without you needing to do anything.
Queued Offline Actions
If the device loses connection while trying to do something (send a message, react, delete a message) the action will fail. However, once connection is regained the action will be executed as soon as possible and you do not need to do anything about it. This comes as an out of the box feature within the scope of offline support.
These queued up actions will be persisted even if the app is closed, the OS kills it or similar. Actions will also be queued up even if you open the app while offline entirely and will work just as well.
These are the actions that support offline queuing:
- Send message (version
7.1.0
and above) - Delete message
- Add reaction
- Delete reaction
How To Cache Images
Available since version 5.3.0
.
Our SDK relies on the default caching provided by React Native (avatars, image attachments, URL preview, etc.). This default solution is far from perfect, and you might see a lot of images missing while operating the app in offline mode. We provide a convenient solution to replace all the underlying usage of the Image
component using the ImageComponent
prop on the Chat
component. Use the ImageComponent
prop to provide a custom component that handles caching and has the same API as react-native’s Image
component.
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.
The following example demonstrates the usage of react-native-fast-image
library to handle the caching of images in chat:
import FastImage from 'react-native-fast-image';
...
<Chat
client={chatClient}
enableOfflineSupport
ImageComponent={FastImage}
/>