Files
vercel__next.js/examples/with-ably/app/ably-client-provider.tsx
Owen Pearson 56fe894489 examples/with-ably: update to App Router + Ably v2 (#94600)
## Summary

Modernizes the `examples/with-ably` example off the deprecated Pages
Router and `@ably-labs/react-hooks` package, onto the App Router and the
React hooks that ship with ably-js v2.

The previous example created the Realtime client at module scope inside
`pages/_app.tsx`, which caused connections to be created during SSR. The
rewrite creates it inside a `useEffect` in a client component
(`app/ably-client-provider.tsx`), gated by an `AblyReadyContext` so
consumer components don't try to call `ably/react` hooks before the
provider is in place.

## Notable changes

- Replace Pages Router with App Router.
- Upgrade `ably` to v2; drop `@ably-labs/react-hooks` (hooks now ship as
`ably/react`).
- Bump React, react-dom and their `@types` to v19 to match
recently-modernized examples like `with-supabase`.
- `app/api/createTokenRequest/route.ts` now returns 400 when `clientId`
is missing rather than coalescing to a shared `"NO_CLIENT_ID"` value.
- Various improvements to README.md

## How I tested these changes

Ran the example with Chrome and Firefox. Verified in two browser
windows:

- Pub/sub: messages published from one window appear in both.
- Server publish: `POST /api/send-message` round-trips and broadcasts.
- Presence: events propagate between windows.
- No errors or warnings in browser console or dev console.

Co-authored-by: Fiona Corden <fiona.corden@ably.com>
2026-06-18 14:12:28 +02:00

45 lines
992 B
TypeScript

"use client";
import { useEffect, useState, type ReactNode } from "react";
import * as Ably from "ably";
import { AblyProvider, ChannelProvider } from "ably/react";
function randomClientId() {
return (
Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15)
);
}
export default function AblyClientProvider({
children,
}: {
children: ReactNode;
}) {
const [clientId] = useState(() => randomClientId());
const [client, setClient] = useState<Ably.Realtime | null>(null);
useEffect(() => {
const ably = new Ably.Realtime({
authUrl: `/api/createTokenRequest?clientId=${clientId}`,
clientId,
});
setClient(ably);
return () => {
ably.close();
};
}, [clientId]);
if (!client) {
return <p>Connecting to Ably...</p>;
}
return (
<AblyProvider client={client}>
<ChannelProvider channelName="some-channel-name">
{children}
</ChannelProvider>
</AblyProvider>
);
}