React Quickstart

npm install pusher-js

Hook + component

import { useEffect, useState } from 'react';
import Pusher from 'pusher-js';
 
interface Message {
  id: string;
  text: string;
  user: string;
}
 
export function ChatRoom({ channelName }: { channelName: string }) {
  const [messages, setMessages] = useState<Message[]>([]);
 
  useEffect(() => {
    const pusher = new Pusher(process.env.NEXT_PUBLIC_PUSHER_KEY!, {
      wsHost: 'ws-sa.mawjly.com',
      wssPort: 443,
      forceTLS: true,
      cluster: 'sa',
      enabledTransports: ['ws', 'wss'],
    });
 
    const channel = pusher.subscribe(channelName);
    channel.bind('message', (msg: Message) => {
      setMessages((prev) => [...prev, msg]);
    });
 
    return () => {
      channel.unbind_all();
      pusher.unsubscribe(channelName);
      pusher.disconnect();
    };
  }, [channelName]);
 
  return (
    <ul>
      {messages.map((m) => (
        <li key={m.id}>
          <strong>{m.user}:</strong> {m.text}
        </li>
      ))}
    </ul>
  );
}

Reusable hook

import { useEffect, useState } from 'react';
import Pusher from 'pusher-js';
 
let _pusher: Pusher | null = null;
 
function getPusher(): Pusher {
  if (_pusher) return _pusher;
  _pusher = new Pusher(process.env.NEXT_PUBLIC_PUSHER_KEY!, {
    wsHost: 'ws-sa.mawjly.com',
    wssPort: 443,
    forceTLS: true,
    cluster: 'sa',
    enabledTransports: ['ws', 'wss'],
  });
  return _pusher;
}
 
export function useChannel<T>(channelName: string, eventName: string): T[] {
  const [events, setEvents] = useState<T[]>([]);
 
  useEffect(() => {
    const ch = getPusher().subscribe(channelName);
    const handler = (e: T) => setEvents((prev) => [...prev, e]);
    ch.bind(eventName, handler);
    return () => {
      ch.unbind(eventName, handler);
      getPusher().unsubscribe(channelName);
    };
  }, [channelName, eventName]);
 
  return events;
}

Use it anywhere:

const messages = useChannel<Message>('chat', 'message');

Private + presence channels

For private-* and presence-* channels you need to point Pusher at your auth endpoint (which signs subscriptions with your secret):

new Pusher(KEY, {
  // ...
  authEndpoint: '/api/broadcasting/auth',
  auth: { headers: { 'X-CSRF-Token': csrf } },
});

See Authorization endpoints.