Skip to content

React Setup

The @pubsubjs/react package provides React hooks and utilities for using PubSubJS in React applications.

Terminal window
bun add @pubsubjs/core @pubsubjs/react
events.ts
import { z } from "zod";
import { defineEvent } from "@pubsubjs/core";
export const events = defineEvent([
{
name: "notification.received",
schema: z.object({
id: z.string(),
message: z.string(),
type: z.enum(["info", "warning", "error"]),
}),
},
{
name: "user.statusChanged",
schema: z.object({
userId: z.string(),
status: z.enum(["online", "offline", "away"]),
}),
},
]);
export type Events = typeof events;
pubsub.ts
import { createPubSub } from "@pubsubjs/react";
import { WebSocketClientTransport } from "@pubsubjs/transport-websocket";
import { events } from "./events";
const transport = new WebSocketClientTransport({
url: "ws://localhost:8080",
});
export const { useSubscribe, usePublish, PubSubProvider } = createPubSub({
events,
transport,
});
App.tsx
import { PubSubProvider } from "./pubsub";
import { NotificationList } from "./NotificationList";
export function App() {
return (
<PubSubProvider>
<NotificationList />
</PubSubProvider>
);
}
NotificationList.tsx
import { useState } from "react";
import { useSubscribe, usePublish } from "./pubsub";
export function NotificationList() {
const [notifications, setNotifications] = useState([]);
// Subscribe to events
useSubscribe("notification.received", (payload) => {
setNotifications((prev) => [...prev, payload]);
});
// Publish events
const publish = usePublish();
const sendNotification = () => {
publish("notification.received", {
id: crypto.randomUUID(),
message: "Hello from React!",
type: "info",
});
};
return (
<div>
<button onClick={sendNotification}>Send Notification</button>
<ul>
{notifications.map((n) => (
<li key={n.id}>{n.message}</li>
))}
</ul>
</div>
);
}
const { useSubscribe, usePublish } = createPubSub({
// Required: Event definitions
events,
// Required: Transport
transport,
// Optional: Skip validation (dangerous!)
skipValidation: false,
});

The hooks are fully typed:

// TypeScript knows the payload type
useSubscribe("notification.received", (payload) => {
// payload.message is typed as string
console.log(payload.message);
// TypeScript error: Property 'invalid' does not exist
console.log(payload.invalid);
});
// TypeScript enforces correct payload
const publish = usePublish();
// OK
publish("notification.received", {
id: "1",
message: "Hello",
type: "info",
});
// TypeScript error: missing 'type'
publish("notification.received", {
id: "1",
message: "Hello",
});

Monitor connection status:

import { useConnectionStatus } from "./pubsub";
function ConnectionIndicator() {
const status = useConnectionStatus();
return (
<div className={`status-${status}`}>
{status === "connected" ? "🟢 Connected" : "🔴 Disconnected"}
</div>
);
}
  • Hooks - Detailed hook documentation
  • Examples - Real-world examples