React Hooks
useSubscribe
Section titled “useSubscribe”Subscribe to events within React components.
Signature
Section titled “Signature”function useSubscribe<TEventName extends EventNames<TEvents>>( eventName: TEventName, handler: (payload: EventPayload<TEvents, TEventName>) => void, deps?: React.DependencyList): void;import { useSubscribe } from "./pubsub";
function MyComponent() { const [messages, setMessages] = useState([]);
useSubscribe("message.received", (payload) => { setMessages((prev) => [...prev, payload]); });
return <div>{/* ... */}</div>;}With Dependencies
Section titled “With Dependencies”Re-subscribe when dependencies change:
function UserMessages({ userId }) { useSubscribe( "message.received", (payload) => { if (payload.userId === userId) { // Handle message for this user } }, [userId] // Re-subscribe when userId changes );}Conditional Subscription
Section titled “Conditional Subscription”function ConditionalSubscriber({ enabled }) { useSubscribe( "notification", (payload) => { console.log("Received:", payload); }, [enabled], { enabled } // Only subscribe when enabled is true );}usePublish
Section titled “usePublish”Get a publish function for sending events.
Signature
Section titled “Signature”function usePublish(): <TEventName extends EventNames<TEvents>>( eventName: TEventName, payload: EventPayload<TEvents, TEventName>) => Promise<void>;import { usePublish } from "./pubsub";
function SendButton() { const publish = usePublish();
const handleClick = async () => { await publish("button.clicked", { buttonId: "send", timestamp: Date.now(), }); };
return <button onClick={handleClick}>Send</button>;}With Loading State
Section titled “With Loading State”function SendForm() { const publish = usePublish(); const [loading, setLoading] = useState(false);
const handleSubmit = async (data) => { setLoading(true); try { await publish("form.submitted", data); } finally { setLoading(false); } };
return ( <form onSubmit={handleSubmit}> <button disabled={loading}> {loading ? "Sending..." : "Submit"} </button> </form> );}useConnectionStatus
Section titled “useConnectionStatus”Monitor the transport connection status.
Signature
Section titled “Signature”function useConnectionStatus(): ConnectionState;// Returns: "disconnected" | "connecting" | "connected" | "reconnecting"import { useConnectionStatus } from "./pubsub";
function ConnectionBanner() { const status = useConnectionStatus();
if (status === "connected") return null;
return ( <div className="connection-banner"> {status === "connecting" && "Connecting..."} {status === "reconnecting" && "Reconnecting..."} {status === "disconnected" && "Disconnected. Retrying..."} </div> );}usePubSub
Section titled “usePubSub”Access the underlying PubSub instance for advanced use cases.
Signature
Section titled “Signature”function usePubSub(): { publisher: Publisher<TEvents>; subscriber: Subscriber<TEvents>; transport: Transport;};import { usePubSub } from "./pubsub";
function AdvancedComponent() { const { publisher, subscriber, transport } = usePubSub();
useEffect(() => { // Direct access to subscriber const unsub = subscriber.on("custom.event", handler); return unsub; }, []);
return <div>{/* ... */}</div>;}Creating Custom Hooks
Section titled “Creating Custom Hooks”Build custom hooks on top of PubSubJS hooks:
useLatestEvent
Section titled “useLatestEvent”function useLatestEvent<T extends EventNames<Events>>(eventName: T) { const [latest, setLatest] = useState<EventPayload<Events, T> | null>(null);
useSubscribe(eventName, (payload) => { setLatest(payload); });
return latest;}
// Usagefunction PriceDisplay() { const price = useLatestEvent("price.updated"); return <span>{price?.value ?? "Loading..."}</span>;}useEventHistory
Section titled “useEventHistory”function useEventHistory<T extends EventNames<Events>>( eventName: T, maxItems = 10) { const [history, setHistory] = useState<EventPayload<Events, T>[]>([]);
useSubscribe(eventName, (payload) => { setHistory((prev) => [...prev.slice(-(maxItems - 1)), payload]); });
return history;}
// Usagefunction ActivityFeed() { const activities = useEventHistory("activity.logged", 50); return ( <ul> {activities.map((a, i) => ( <li key={i}>{a.description}</li> ))} </ul> );}useEventCallback
Section titled “useEventCallback”function useEventCallback<T extends EventNames<Events>>(eventName: T) { const publish = usePublish();
return useCallback( (payload: EventPayload<Events, T>) => { return publish(eventName, payload); }, [publish, eventName] );}
// Usagefunction ChatInput() { const sendMessage = useEventCallback("chat.message");
const handleSubmit = (text) => { sendMessage({ text, timestamp: Date.now() }); };
return <input onSubmit={handleSubmit} />;}