# React Hooks
Leverage the power of Ably in your React applications using idiomatic, easy-to-use React Hooks. This package enables you to:
* Subscribe to messages on Ably [channels](https://ably.com/docs/channels).
* Publish messages using the channel instances provided by hooks.
* Enter the [presence set](https://ably.com/docs/presence-occupancy/presence) on channels.
* Subscribe to presence updates on channels.
* Trigger presence updates.
The following hooks are available:
| Hook | Description |
|------|-------------|
| **[useChannel](#useChannel)** | The `useChannel` hook subscribes to a channel and receives messages from it |
| **[usePresence](#usePresence)** | The `usePresence` hook enters clients into the presence set |
| **[usePresenceListener](#usePresenceListener)** | The `usePresenceListener` hook subscribes to presence events on a channel |
| **[useConnectionStateListener](#useConnectionStateListener)** | The `useConnectionStateListener` hook attaches a listener to be notified of connection state changes in the Ably client |
| **[useChannelStateListener](#useChannelStateListener)** | The `useChannelStateListener` hook attaches a listener to be notified of channel state changes |
| **[useAbly](#useAbly)** | The `useAbly` hook grants access to the Ably client instance provided by the AblyProvider context |
All hooks manage the lifecycle of Ably SDK instances for you, ensuring that you [subscribe](https://ably.com/docs/pub-sub#subscribe) and [unsubscribe](https://ably.com/docs/pub-sub/advanced#unsubscribe) to channels and events when your React components re-render.
## Install
Ably JavaScript SDK versions >= 1.2.44 include React Hook functionality as standard. You don't need to install any additional packages.
```shell
npm install --save ably
```
## Authenticate
An [API key](https://ably.com/docs/auth#api-keys) is required to authenticate with Ably. API keys are used either to authenticate directly with Ably using [basic authentication](https://ably.com/docs/auth/basic), or to generate tokens for untrusted clients using [token authentication](https://ably.com/docs/auth/token).
[Sign up](https://ably.com/sign-up) to Ably to create an API key in the [dashboard](https://ably.com/dashboard) or use the [Control API](https://ably.com/docs/platform/account/control-api) to create an API programmatically.
## Usage
### Setting up the Ably Provider
Use the `AblyProvider` component to connect to Ably. This component should be placed high up in your component tree, wrapping every component that needs to access Ably.
You can create your own client and pass it to the context provider:
```react
import * as Ably from 'ably';
import { AblyProvider } from 'ably/react';
import { createRoot } from 'react-dom/client';
const container = document.getElementById('root')!;
const root = createRoot(container);
const client = new Ably.Realtime({ key: '', clientId: '' });
root.render(
);
```
#### Multiple clients
If you need to use multiple Ably clients on the same page, you can keep your clients in separate `AblyProvider` components. If nesting AblyProviders, you can pass a string ID for each client as a property to the provider.
```react
root.render(
);
```
### Channel Provider
Use the `ChannelProvider` to define the [channels](https://ably.com/docs/channels) you want to use in other hooks.
```react
```
You can also set [channel options](https://ably.com/docs/channels/options) in the `ChannelProvider` component:
The following is an example of setting the [rewind](https://ably.com/docs/channels/options/rewind) channel option:
```react
```
Use `deriveOptions` to set a [subscription filter](https://ably.com/docs/pub-sub/advanced#subscription-filters) and only receive messages that satisfy a filter expression:
```react
const deriveOptions = { filter: 'headers.email == `"rob.pike@domain.com"` || headers.company == `"domain"`' }
return (
)
```
### useChannel
The `useChannel` hook enables you to [subscribe to a channel](https://ably.com/docs/pub-sub#subscribe) and receive its messages. It can be combined with the React `useState` hook to maintain a list of messages in your app state.
```react
const [messages, updateMessages] = useState([]);
const { channel } = useChannel('your-channel-name', (message) => {
updateMessages((prev) => [...prev, message]);
});
```
You can also filter messages by providing a message name to the `useChannel` function:
```react
const { channel } = useChannel('your-channel-name', 'messageName', (message) => {
console.log(message);
});
```
Use the `publish` function to publish messages to the channel:
```react
const { publish } = useChannel("your-channel-name")
publish("test-message", { text: "message text" });
```
### usePresence
The `usePresence` hook enables you to [enter the presence set](https://ably.com/docs/presence-occupancy/presence#member-data).
```react
const { updateStatus } = usePresence('your-channel-name');
// Optionally pass a second argument to 'usePresence' to set a client's initial member data
const { updateStatus } = usePresence('your-channel-name', 'initialStatus');
// The `updateStatus` function can be used to update the presence data for the current client
updateStatus('newStatus');
```
### usePresenceListener
The `usePresenceListener` hook enables you to [subscribe to presence](https://ably.com/docs/presence-occupancy/presence#subscribe) events on a channel, notifying you when a user enters or leaves the presence set, or updates their member data.
```react
const { presenceData } = usePresenceListener('your-channel-name');
// Convert presence data to list items to render
const peers = presenceData.map((msg, index) =>
{msg.clientId}: {msg.data}
);
```
### useConnectionStateListener
The `useConnectionStateListener` hook enables you to attach a listener to be notified of [connection state](https://ably.com/docs/connect/states) changes. This can be useful for detecting when a client has lost its connection.
```react
useConnectionStateListener((stateChange) => {
console.log(stateChange.current); // the new connection state
console.log(stateChange.previous); // the previous connection state
console.log(stateChange.reason); // if applicable, an error indicating the reason for the connection state change
});
```
You can also pass a filter to only listen for specific connection states:
```react
useConnectionStateListener('failed', listener); // the listener only gets called when the connection state becomes failed
useConnectionStateListener(['failed', 'suspended'], listener); // the listener only gets called when the connection state becomes failed or suspended
```
### useChannelStateListener
The `useChannelStateListener` hook enables you to attach a listener to be notified of [channel state](https://ably.com/docs/channels/states) changes. This can be useful for detecting when a channel error has occurred.
```react
useChannelStateListener((stateChange) => {
console.log(stateChange.current); // the new channel state
console.log(stateChange.previous); // the previous channel state
console.log(stateChange.reason); // if applicable, an error indicating the reason for the channel state change
});
```
Similar to [useConnectionStateListener](#useConnectionStateListener), you can also pass in a filter to only listen to specific channel states:
```react
useChannelStateListener('failed', listener); // the listener only gets called when the channel state becomes failed
useChannelStateListener(['failed', 'suspended'], listener); // the listener only gets called when the channel state becomes failed or suspended
```
### useAbly
The `useAbly` hook enables access to the Ably client used by the [AblyProvider](#ably-provider) context. This can be used to access APIs which aren't available through the React Hooks submodule.
```react
const client = useAbly();
client.authorize();
```
## Error handling
When using Ably React Hooks, you may encounter errors. The [useChannel](#useChannel) and [usePresence](#usePresence) hooks return connection and channel errors, enabling you to handle them in your components.
```react
const { connectionError, channelError } = useChannel('your-channel-name', messageHandler);
```