Skip to content

Commit

Permalink
Add migration guide for react hooks for ably-js v2
Browse files Browse the repository at this point in the history
Resolves #1684
  • Loading branch information
VeskeR committed Mar 15, 2024
1 parent c64732c commit 95d78bd
Showing 1 changed file with 203 additions and 1 deletion.
204 changes: 203 additions & 1 deletion docs/react-migration-guide.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,207 @@
# React hooks upgrade / migration guide

## Version ?? to ??

### ChannelProvider

In previous versions, you were able to provide channel options as a parameter in the `useChannel`/`usePresence` hooks. This often led to errors when using hooks with the same channel name but different options, or when attempting to dynamically change options for a channel.

To address these issues, the new version introduces the `ChannelProvider` component to define the channels you wish to use and their options. The ability to provide channel options using the `options` or `deriveOptions` parameters in `useChannel`/`usePresence` hooks has been removed.

Replace code that used `options` in the `useChannel` hook:

```jsx
const { channel } = useChannel(
{ channelName: 'your-channel-name', options: { params: { rewind: '1' } } },
(message) => {
console.log(message);
},
);
```

With this:

```jsx
// in a parent component:
return <ChannelProvider channelName="your-channel-name" options={{ params: { rewind: '1' } }}>
{children}
</ChannelProvider>

// in a child component:
const { channel } = useChannel({ channelName: 'your-channel-name' }, (message) => {
console.log(message);
});
```

Replace code that used `deriveOptions` in `useChannel` hook:

```jsx
useChannel(
{
channelName: 'your-derived-channel-name',
deriveOptions: { filter: 'headers.role == `"marketing"`' },
},
(message) => {
console.log(message);
},
);
```

With this:

```jsx
// in a parent component:
return <ChannelProvider channelName="your-derived-channel-name" deriveOptions={{ filter: 'headers.role == `"marketing"`' }}>
{children}
</ChannelProvider>

// in a child component:
useChannel({ channelName: 'your-derived-channel-name' }, (message) => {
console.log(message);
});
```

Replace code that used `options` in `usePresence` hook:

```jsx
const { updateStatus } = usePresence(
{ channelName: 'presence-channel-name', options: { modes: ['PRESENCE'] } },
{ foo: 'bar' },
);
```

With this:

```jsx
// in a parent component:
return <ChannelProvider channelName="presence-channel-name" options={{ modes: ['PRESENCE'] }}>
{children}
</ChannelProvider>

// in a child component:
const { updateStatus } = usePresence({ channelName: 'presence-channel-name' }, { foo: 'bar' });
```

Additionally, if you were calling `.setOptions()` on a channel instance returned by the `useChannel` hook before, you must remove those calls and instead modify options provided to the `ChannelProvider` component if you want to change channel options during runtime.

Change this:

```jsx
const { channel } = useChannel({ channelName: 'your-channel-name' }, (message) => {
console.log(message);
});
channel.setOptions({ params: { rewind: '1' } });
```

To this:

```jsx
// in a parent component:
// change channel options during runtime using state
const [options, setOptions] = useState({});
return <ChannelProvider channelName="your-channel-name" options={options}>
{children}
</ChannelProvider>

// in a child component:
const { channel } = useChannel({ channelName: 'your-channel-name' }, (message) => {
console.log(message);
});
```

### `usePresence` is split into two hooks

The functionality of the `usePresence` hook has been split into two separate hooks.

The `usePresence` hook can now only be used to enter the presence with optional initial state and update the presence status for the current client. It no longer returns the `presenceData` value and does not accept the `onPresenceUpdated` callback as its third parameter.

To listen for presence updates, a new hook called `usePresenceListener` has been introduced. This hook returns the `presenceData` object previously returned by `usePresence` and accepts an `onPresenceMessageReceived` callback as its second parameter, which is called on new presence messages.

Replace this:

```jsx
const { presenceData, updateStatus } = usePresence(
{ channelName: 'presence-channel-name' },
{ foo: 'bar' },
(update) => {
console.log(update);
},
);
```

With this:

```jsx
const { updateStatus } = usePresence({ channelName: 'presence-channel-name' }, { foo: 'bar' });
const { presenceData } = usePresenceListener({ channelName: 'presence-channel-name' }, (update) => {
console.log(update);
});
```

### Renaming `id` to `ablyId`

All instances of the `id` field, which were used to specify the `AblyProvider` component and the underlying Ably client to use, have been renamed to `ablyId`.

Replace this:

```jsx
// in a parent component:
const client = new Ably.Realtime(options);

return <AblyProvider client={ably} id="foo">
{children}
</AblyProvider>

// in a child component:
useChannel({ channelName: 'your-channel-name', id: 'foo' }, (message) => {
console.log(message);
});
```

With this:

```jsx
// in a parent component:
const client = new Ably.Realtime(options);

return <AblyProvider client={ably} ablyId="foo">
<ChannelProvider channelName="your-channel-name" ablyId="foo">
{children}
</ChannelProvider>
</AblyProvider>

// in a child component:
useChannel({ channelName: 'your-channel-name', ablyId: 'foo' }, (message) => {
console.log(message);
});
```

### New convenience function `publish` in `useChannel`

A new convenience function, `publish`, is now being returned by the `useChannel` hook. It performs the same function as calling `channel.publish()`. Additionally, using this dedicated `publish` function allows you to send messages to derived channels (channels with a filter qualifier) without attaching to the channel or using other workarounds.

It is recommended to use the dedicated `publish` function returned by the `useChannel` hook instead of calling `channel.publish()`.

Replace this:

```jsx
const { channel } = useChannel({ channelName: 'your-channel-name' });

channel.publish('test-message', {
text: 'message text',
});
```

With this:

```jsx
const { publish } = useChannel({ channelName: 'your-channel-name' });

publish('test-message', {
text: 'message text',
});
```

## Version 2.x to 3.x

### Hooks now return object
Expand All @@ -14,7 +216,7 @@ const { channel, ably } = useChannel("your-channel-name", (message) => { /* ...
const { presenceData, updateStatus } = usePresence("your-channel-name");
```

### Replacing `configureAbly` with `AblyProvider`
### Replacing `configureAbly` with `AblyProvider`

In versions 1 and 2 of our react-hooks, we exported a function called `configureAbly` which was used to register an Ably client instance to global state.
This caused a few issues (most notably it made the hooks difficult to use with hot module reloading), so we have replaced the global configuration function with a context provider (`AblyProvider`)
Expand Down

0 comments on commit 95d78bd

Please sign in to comment.