crosshook
v1.4.0
Published
> Tiny hook-first event bridge for decoupled React component > communication.
Readme
crosshook
Tiny hook-first event bridge for decoupled React component communication.
crosshook lets React components communicate without prop drilling,
context nesting, or heavyweight state managers.
Perfect for UI orchestration like modals, toasts, loaders, and notifications.
✨ Features
✅ Hook-first API
✅ No providers required
✅ Tiny footprint
✅ Lifecycle-safe (auto cleanup)
✅ Strict Mode friendly
✅ TypeScript ready
📦 Installation
npm install crosshookor
yarn add crosshook🚀 Quick Start
✅ Register a Listener
import { useRegister } from "crosshook";
function Toast() {
useRegister("toast.show", (payload: { message: string }) => {
console.log(payload.message);
});
return null;
}✅ Call an Event
import { useBridge } from "crosshook";
function SaveButton() {
const { call } = useBridge();
return (
<button
onClick={() =>
call("toast.show", { message: "Saved successfully!" })
}
>
Save
</button>
);
}🎯 Common Use Cases
🔔 Toast Notifications
useRegister("toast.show", ({ message }) => {
setToast(message);
});
call("toast.show", { message: "Profile updated!" });🪟 Modal Control
useRegister("modal.open", () => setOpen(true));
useRegister("modal.close", () => setOpen(false));
call("modal.open");⏳ Global Loader
useRegister("loader.show", () => setLoading(true));
useRegister("loader.hide", () => setLoading(false));
call("loader.show");
call("loader.hide");🧠 API
useBridge()
Returns bridge actions.
const { call } = useBridge();call(eventName, payload?)
Triggers all listeners registered for the event.
useRegister(eventName, handler)
Registers a listener.
useRegister("event.name", (payload) => {
...
});✔ Automatically cleaned up on unmount
✔ Safe in React Strict Mode
call(eventName, payload?)
Non-hook version (can be used outside React).
import { call } from "crosshook";
call("toast.show", { message: "Hello!" });register(eventName, handler)
Manual registration.
import { register } from "crosshook";
const unregister = register("event", handler);
// later
unregister();⚠️ Best Practices
✅ Good For
✔ UI interactions
✔ Modals
✔ Toasts
✔ Notifications
✔ Cross-tree communication
❌ Avoid Using For
✖ Business logic orchestration
✖ App state management
✖ Server/cache state
✖ Data persistence
Use React state / Zustand / Redux instead.
🔷 TypeScript Usage (Optional)
crosshook supports global event typing via module augmentation.
This provides:
✅ Event name autocomplete ✅ Payload type safety ✅ No generics required
✅ 1. Create crosshook.d.ts
Place anywhere TypeScript can see (recommended: src/):
// src/crosshook.d.ts
import "crosshook";
declare module "crosshook" {
interface CrosshookEvents {
"toast.show": { message: string };
"modal.open": { id: string };
"user.login": { userId: number };
}
}✅ 2. Use normally
import { useRegister, call } from "crosshook";
// Listener
useRegister("toast.show", (payload) => {
// payload is typed as { message: string }
console.log(payload.message);
});
// Caller
call("toast.show", { message: "Hello!" });
// 👆 TypeScript error if payload wrong🧹 Cleanup Behavior
Listeners automatically unsubscribe when components unmount.
No memory leaks. No manual cleanup required.
🛠 Example Pattern
// Listener
useRegister("user.select", (user) => {
setUser(user);
});
// Caller
call("user.select", { id: 1, name: "Manu" });📏 Bundle Size
Designed to be extremely lightweight.
📜 License
MIT
❤️ Why crosshook?
Because not every interaction needs:
❌ Prop drilling
❌ Deep context trees
❌ Heavy state libraries
Sometimes you just need a tiny event bridge.
