---
sidebar_position: 7
---

# React, React Native and Capacitor

## React

```tsx
import { RealtimeProvider, useChannel, usePresence, useCalls, CallScreen, CallButton, RoomButton } from '@wordplus/realtime/react';

export default function App() {
    return (
        <RealtimeProvider options={ { site: 's1500000007', worker: '/realtime-worker.js', rooms: '/realtime-rooms.min.js' } }>
            <CallScreen />
            <Order id={ 42 } />
        </RealtimeProvider>
    );
}

function Order( { id } ) {
    const [ status, setStatus ] = useState( 'open' );
    const channel = useChannel( `private-orders-${ id }`, { updated: ( data ) => setStatus( data.status ) } );
    const agents = usePresence( 'presence-agents' );

    return (
        <>
            <p>{ status } { channel.state === 'failed' && channel.error }</p>
            { agents.map( ( a ) => <CallButton key={ a.id } to={ Number( a.id ) } call={ `support-${ id }` } name={ a.info?.name }>Call { a.info?.name }</CallButton> ) }
        </>
    );
}
```

| | |
|---|---|
| `<RealtimeProvider options onError>` | connects once for everything inside, and closes when it goes; `options` are `connect()`'s or your server's `config()` |
| `useRealtime()` | the connection (`Realtime`), or `null` until it's up |
| `useChannel( name, handlers )` | listens while the component is on the page; gives `{ state, error, trigger( event, data ) }`; `null` listens to nothing |
| `usePresence( name )` | the members, `[ { id, info } ]`, kept up to date |
| `useCalls()` | `{ calls, incoming }`: the page's calls once loaded, and those ringing |
| `<CallScreen strings? />` | starts the call screen ([calls](calls.md#the-call-screen)) |
| `<CallButton to call type name avatar>`, `<RoomButton room type title>` | its buttons |

Several components may listen to one channel: it is left when the last of them goes.

**Next.js:** the React entry is a client module (`'use client'`). Render the user's settings on the server to skip a request: `const config = await realtime.config( userId )` in a server component, then `<RealtimeProvider options={ config }>`.

## React Native

```ts
import 'react-native-get-random-values';   // first: sealing needs crypto.getRandomValues
import { connect } from '@wordplus/realtime/native';

const rt = await connect( {
    site: 's1500000007',
    endpoint: 'https://app.example.com/api/realtime',          // in full
    headers: { Authorization: 'Bearer ' + session.token },      // how your server knows the user
} );
```

- Channels, presence, client events, publishing and the directory, sealed as in a browser.
- No worker and no address: a native app connects by itself and sends no Origin, which WordPlus Cloud lets in.
- Your server's `user( request )` reads the user from the `Authorization` header, or whatever your app sends.
- **Calls in React Native come later** (they need a WebRTC module).

## Capacitor and Ionic

An app in Capacitor or Ionic is a page: use `@wordplus/realtime` as in a browser, and add its address to your app in WordPlus Cloud: `capacitor://localhost` on iOS, `https://localhost` (or `http://localhost`) on Android, `ionic://localhost` for Ionic's. Calls work there as in the browser. Your routes need their full address (`endpoint: 'https://app.example.com/api/realtime'`), and your server must answer the app's address with CORS.
