Documentation Index
Fetch the complete documentation index at: https://docs.fanfare.io/llms.txt
Use this file to discover all available pages before exploring further.
Context Hook
The useFanfare hook provides access to the underlying Fanfare SDK instance within the React context.
useFanfare
function useFanfare(): FanfareSDK;
Returns the initialized FanfareSDK instance.
Basic Usage
import { useFanfare } from "@waitify-io/fanfare-sdk-react";
function MyComponent() {
const fanfare = useFanfare();
// Access any SDK module
const handleEnterQueue = async () => {
await fanfare.queues.enter("queue_123");
};
return <button onClick={handleEnterQueue}>Enter Queue</button>;
}
Error Handling
The hook throws if used outside a FanfareProvider:
function ComponentOutsideProvider() {
// This will throw:
// "useFanfare must be used within a FanfareProvider"
const fanfare = useFanfare();
return null;
}
Always ensure components using useFanfare are descendants of FanfareProvider:
function App() {
return (
<FanfareProvider organizationId="org_xxx" publishableKey="pk_live_xxx">
<MyComponent /> {/* This works */}
</FanfareProvider>
);
}
When to Use useFanfare
Use useFanfare When
- You need direct access to SDK modules
- You want to call SDK methods imperatively
- You’re building custom hooks on top of the SDK
- You need to access modules not covered by existing hooks
Use Specialized Hooks When
- You need reactive state (use
useQueue, useDraw, etc.)
- You want automatic event subscription
- You need loading/error state management
- You want to leverage the hook patterns
Examples
Direct Module Access
import { useFanfare } from "@waitify-io/fanfare-sdk-react";
function DirectAccess() {
const fanfare = useFanfare();
// Access auth module
const handleLogin = async () => {
await fanfare.auth.requestOtp({ email: "[email protected]" });
};
// Access beacon module
const trackEvent = () => {
fanfare.beacon.track({
event: "button_click",
properties: { button: "cta" },
});
};
return (
<div>
<button onClick={handleLogin}>Login</button>
<button onClick={trackEvent}>Track</button>
</div>
);
}
Subscribing to Events
import { useEffect } from "react";
import { useFanfare } from "@waitify-io/fanfare-sdk-react";
function EventSubscriber() {
const fanfare = useFanfare();
useEffect(() => {
const unsubscribe = fanfare.on("queue:admitted", (data) => {
console.log("Admitted to queue:", data.queueId);
// Navigate to checkout
});
return () => {
unsubscribe();
};
}, [fanfare]);
return <div>Listening for admission...</div>;
}
Custom Hook Pattern
import { useCallback, useState, useEffect } from "react";
import { useFanfare } from "@waitify-io/fanfare-sdk-react";
import type { Queue } from "@waitify-io/fanfare-sdk-core";
function useQueueDetails(queueId: string) {
const fanfare = useFanfare();
const [queue, setQueue] = useState<Queue | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
let mounted = true;
async function fetchQueue() {
try {
setIsLoading(true);
const data = await fanfare.queues.get(queueId);
if (mounted) {
setQueue(data);
setError(null);
}
} catch (err) {
if (mounted) {
setError(err as Error);
}
} finally {
if (mounted) {
setIsLoading(false);
}
}
}
fetchQueue();
return () => {
mounted = false;
};
}, [fanfare, queueId]);
const refetch = useCallback(async () => {
const data = await fanfare.queues.get(queueId);
setQueue(data);
return data;
}, [fanfare, queueId]);
return { queue, isLoading, error, refetch };
}
Building a Multi-Queue Dashboard
import { useEffect, useState } from "react";
import { useFanfare } from "@waitify-io/fanfare-sdk-react";
import type { QueueParticipation } from "@waitify-io/fanfare-sdk-core";
function QueueDashboard() {
const fanfare = useFanfare();
const [activeQueues, setActiveQueues] = useState<Record<string, QueueParticipation>>({});
useEffect(() => {
// Get initial state
setActiveQueues(fanfare.queues.getActiveQueues());
// Subscribe to updates
const unsubscribes = [
fanfare.on("queue:entered", () => {
setActiveQueues(fanfare.queues.getActiveQueues());
}),
fanfare.on("queue:left", () => {
setActiveQueues(fanfare.queues.getActiveQueues());
}),
fanfare.on("queue:position-changed", () => {
setActiveQueues(fanfare.queues.getActiveQueues());
}),
fanfare.on("queue:admitted", () => {
setActiveQueues(fanfare.queues.getActiveQueues());
}),
];
return () => {
unsubscribes.forEach((unsub) => unsub());
};
}, [fanfare]);
return (
<div>
<h2>Your Active Queues</h2>
{Object.entries(activeQueues).map(([queueId, participation]) => (
<div key={queueId}>
<p>Queue: {queueId}</p>
<p>Status: {participation.status}</p>
<p>Position: {participation.position}</p>
</div>
))}
</div>
);
}
Accessing Experience Journey
import { useEffect, useRef } from "react";
import { useFanfare } from "@waitify-io/fanfare-sdk-react";
import type { ExperienceJourney } from "@waitify-io/fanfare-sdk-core";
function JourneyComponent({ experienceId }: { experienceId: string }) {
const fanfare = useFanfare();
const journeyRef = useRef<ExperienceJourney | null>(null);
useEffect(() => {
// Create or get existing journey
const journey = fanfare.experiences.createJourney(experienceId);
journeyRef.current = journey;
// Subscribe to state changes
const unsubscribe = journey.state.listen((snapshot) => {
console.log("Journey stage:", snapshot.journeyStage);
console.log("Sequence stage:", snapshot.sequenceStage);
});
return () => {
unsubscribe();
};
}, [fanfare, experienceId]);
const startJourney = async () => {
if (journeyRef.current) {
await journeyRef.current.start();
}
};
return <button onClick={startJourney}>Start Journey</button>;
}
TypeScript
import { useFanfare } from "@waitify-io/fanfare-sdk-react";
import type { FanfareSDK } from "@waitify-io/fanfare-sdk-core";
function TypedComponent() {
// fanfare is typed as FanfareSDK
const fanfare: FanfareSDK = useFanfare();
// All modules are fully typed
const auth = fanfare.auth; // AuthModule
const queues = fanfare.queues; // QueueModule
const draws = fanfare.draws; // DrawModule
const auctions = fanfare.auctions; // AuctionModule
return null;
}
Best Practices
1. Use Specialized Hooks When Available
// Prefer this
import { useQueue } from "@waitify-io/fanfare-sdk-react";
function QueueComponent() {
const { queue, position, enter, leave } = useQueue("queue_123");
// Automatic state management, event subscriptions, cleanup
}
// Over this (unless you need custom behavior)
import { useFanfare } from "@waitify-io/fanfare-sdk-react";
function QueueComponent() {
const fanfare = useFanfare();
// Manual state management required
}
2. Clean Up Event Subscriptions
useEffect(() => {
const unsubscribes = [fanfare.on("queue:admitted", handleAdmitted), fanfare.on("queue:denied", handleDenied)];
return () => {
unsubscribes.forEach((unsub) => unsub());
};
}, [fanfare]);
3. Handle Async Operations Safely
useEffect(() => {
let mounted = true;
async function fetchData() {
const result = await fanfare.queues.status("queue_123");
if (mounted) {
setStatus(result);
}
}
fetchData();
return () => {
mounted = false;
};
}, [fanfare]);