Skip to content

About

React and React Native hooks for Tinode chat, with full TypeScript types

Resources

Code of conduct

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

react-native-tinode

React hooks and providers for Tinode chat on React Native and the web, on top of the official JavaScript SDK, tinode-sdk.

  • iOS, Android and web. Works in Expo Go and in bare React Native.
  • No native code.
  • TypeScript types for the whole SDK: protocol messages, topics, Drafty documents and contact cards.
  • Offline cache: IndexedDB on the web; expo-sqlite, MMKV or AsyncStorage on native, in one line.

Installation

yarn add react-native-tinode

tinode-sdk comes with it. Until the next tinode-sdk release is on npm, it is installed from a pinned commit of the tinode-js devel branch, so installing needs git and npm on the machine and access to github.com (all three are on CI runners and EAS build images). Networks that block git or GitHub cannot install it until then.

Quick start

import {
  TinodeProvider,
  useConnection,
  useLogin,
  useMeTopic,
} from 'react-native-tinode';

export default function App() {
  return (
    <TinodeProvider
      config={{
        appName: 'MyApp/1.0',
        host: 'api.tinode.co',
        apiKey: 'AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K',
        secure: true,
      }}
    >
      <Main />
    </TinodeProvider>
  );
}

function Main() {
  const { status } = useConnection();
  const { loginBasic, user } = useLogin();
  const { contacts } = useMeTopic();
}

A complete app (login, contacts, chat with paging and typing indicator) lives in example/. To point it at a local Tinode server, which comes with test users like alice/alice123:

EXPO_PUBLIC_TINODE_HOST=localhost:6060 EXPO_PUBLIC_TINODE_SECURE=false yarn example start

On the Android emulator the example rewrites localhost to 10.0.2.2.

Using the client directly

Tinode is the tinode-sdk client, so its documentation applies.

import { createTinode } from 'react-native-tinode';

const tinode = createTinode({ appName: 'MyApp/1.0', host: 'api.example.com', apiKey: '...' });

await tinode.connect();
await tinode.loginBasic('alice', 'secret');

const me = tinode.getMeTopic();
me.onContactUpdate = (what, contact) => console.log(what, contact.name);
await me.subscribe(me.startMetaQuery().withLaterSub().withDesc().build());

createTinode fills in platform from Platform.OS. You can also use new Tinode(config) yourself.

Hooks

Hook Returns
useTinode() the Tinode instance
useConnection() { status, retryIn, error }, status is disconnected, connecting, connected or authenticated
useLogin() { loginBasic, loginToken, logout, user, token, error }
useMeTopic() { contacts, isSubscribed, error }
useTopic(name) { topic, isSubscribed, desc, subscribers, subscribe, leave, error }
useMessages(name, { pageSize }) { messages, hasMore, loading, loadMore, send, status, markRead, error }
useTyping(name) { typingUsers, notifyTyping }

Several components can use the same topic. The subscription is shared and the topic is left shortly after the last one unmounts.

Tinode callbacks such as onData hold a single function. The hooks do not overwrite your own handlers: listeners are added through attach(target, 'onData', fn), which you can use too.

useLogin keeps the auth token in memory only. To stay signed in across launches, see docs/persistence/auth-token.md.

Reconnecting

The provider reconnects when the app comes back to the foreground. When the connection drops, the client retries with a growing delay. To retry at once when the network comes back, pass NetInfo in the config:

import NetInfo from '@react-native-community/netinfo';

<TinodeProvider config={{ ...config, netInfo: NetInfo }}>

netInfo is anything with addEventListener(listener) that returns an unsubscribe function and calls the listener with { isConnected }, so a small wrapper over the browser online and offline events works on the web too.

Persistence

By default nothing is cached (persist: false). With a cache, your app can show chats at once on start, and chats opened before stay readable offline.

Your app Store Guide
Expo (Expo Go or a development build) expo-sqlite/kv-store docs/persistence/expo-sqlite.md
Bare React Native react-native-mmkv docs/persistence/mmkv.md
Already uses AsyncStorage @react-native-async-storage/async-storage docs/persistence/async-storage.md
Web nothing to install, persist: true uses IndexedDB docs/persistence/README.md
import Storage from 'expo-sqlite/kv-store';
import { createTinode, KeyValueAdapter } from 'react-native-tinode';

createTinode({ ...config, persist: true, storage: new KeyValueAdapter(Storage) });

The store is your app's dependency, not this library's. To keep users signed in across launches, see docs/persistence/auth-token.md. How the cache works, sharing a store and limits: docs/persistence/README.md.

Files

tinode.getLargeFileHelper() uploads and downloads attachments.

  • upload() accepts a web Blob/File or a React Native file object { uri, name, type }.
  • download() saves the file in the browser. It does not work on native yet: the current tinode-sdk needs a DOM for it. Until the fix is released upstream, download attachments yourself with fetch and the auth token.

Push notifications

import messaging from '@react-native-firebase/messaging';
import { registerDeviceToken } from 'react-native-tinode';

registerDeviceToken(tinode, await messaging().getToken());

With Expo, use (await Notifications.getDevicePushTokenAsync()).data. The server sends FCM data messages; how to show them is up to the app.

What this package adds to tinode-sdk

  • Providers and hooks with shared topic subscriptions, paging and typing state.
  • TypeScript types. tinode-sdk is plain JavaScript and ships no types.
  • Two small polyfills for Hermes, installed only when missing: Intl.Segmenter (grapheme level only, used by Drafty) and a UTF-8 TextDecoder (used by vCard import). Import react-native-tinode before tinode-sdk so they are in place when the SDK loads.
  • isCommError(error), because tinode-sdk does not export its CommError class.

See docs/DECISIONS.md for the reasoning.

Contributing

License

Apache-2.0. Uses tinode-sdk by Tinode LLC, see NOTICE.

About

React and React Native hooks for Tinode chat, with full TypeScript types

Resources

Code of conduct

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages