diff --git a/README.md b/README.md index 768d32615..7adf94918 100644 --- a/README.md +++ b/README.md @@ -195,16 +195,33 @@ If you're hitting a "connection limit exceeded" error and see rising connection Even for `use client` components, Next.js may execute them on the server during pre-rendering. This can create unintended `Ably.Realtime` connections from Node.js that remain open until you restart the development server. -Prevent server-side connections using `autoConnect` and a window check: +To prevent server-side connections, create the Ably client inside a `useEffect` hook so it only runs in the browser: -```typescript -const client = new Ably.Realtime({ - key: 'your-ably-api-key', - autoConnect: typeof window !== 'undefined', -}); +```tsx +'use client'; + +import { useEffect, useState } from 'react'; +import * as Ably from 'ably'; +import { AblyProvider } from 'ably/react'; + +export default function AblyClientProvider({ children }) { + const [client, setClient] = useState(null); + + useEffect(() => { + const ably = new Ably.Realtime({ authUrl: '/token', authMethod: 'POST', clientId: 'demo' }); + setClient(ably); + return () => { + ably.close(); + }; + }, []); + + if (!client) return
Loading...
; + + return {children}; +} ``` -Creating the client inside [React](https://github.com/ably/ably-js/blob/main/docs/react.md#Usage) components can lead to a new connection on every render. To prevent this, move the new `Ably.Realtime()` call outside of component functions. +Avoid creating the client inside [React](https://github.com/ably/ably-js/blob/main/docs/react.md#Usage) component bodies, as this leads to a new connection on every render. Use the `useEffect` + `useState` pattern shown above, or move the client to a shared provider at the layout level. In development environments that use Hot Module Replacement (HMR), such as React, Vite, or Next.js, saving a file can recreate the Ably.Realtime client, while previous instances remain connected. Over time, this leads to a growing number of active connections with each code edit. To fix: Move the client to a separate file (e.g., `ably-client.js`) and import it. This ensures the client is recreated only when that file changes. @@ -237,7 +254,7 @@ This is a common problem in App Router for a number of packages (for example, se -### Genral errors during development +### General errors during development If you encounter an error such as `connection limit exceeded` during development, it may be caused by several issues. @@ -246,15 +263,34 @@ If you encounter an error such as `connection limit exceeded` during development #### Server-side rendering (SSR) -Use the `autoConnect` option to prevent the client from connecting when rendered on the server: +Create the Ably client inside a `useEffect` hook to prevent it from connecting when rendered on the server: -```typescript -const client = new Ably.Realtime({ key: 'your-ably-api-key', autoConnect: typeof window !== 'undefined' }); +```tsx +'use client'; + +import { useEffect, useState } from 'react'; +import * as Ably from 'ably'; + +export default function MyComponent() { + const [client, setClient] = useState(null); + + useEffect(() => { + const ably = new Ably.Realtime({ authUrl: '/token', authMethod: 'POST', clientId: 'demo' }); + setClient(ably); + return () => { + ably.close(); + }; + }, []); + + if (!client) return
Loading...
; + + // Use client here +} ``` #### Component re-renders -Avoid creating the client inside React components. Instead, move the client instantiation outside of the component to prevent it from being recreated on every render. +Avoid creating the client inside React component bodies, as this creates a new connection on every render. Use the `useEffect` + `useState` pattern shown above to ensure the client is created once. #### Hot module replacement (HMR)