React SDK
React hooks and components for integrating Quotient into React applications
Installation
npm install @quotientjs/react
QuotientProvider
Context provider that initializes and manages the SDK. Wrap your app with this component to use Quotient hooks in child components.
| Prop | Type | Required | Description |
|---|---|---|---|
clientOptions.apiKey | string | Yes | Your public API key |
clientOptions.baseUrl | string | No | Custom API endpoint |
autoTrackPageViews | boolean | No | Auto-track page views on mount (default false) |
import { QuotientProvider } from "@quotientjs/react";
function App() {
return (
<QuotientProvider
clientOptions={{ apiKey: "pk_your_public_api_key" }}
autoTrackPageViews={true}
>
{children}
</QuotientProvider>
);
}
useQuotient
Access the Quotient client and context within React components.
import { useQuotient } from "@quotientjs/react";
function MyComponent() {
const {
client, // QuotientClient instance or null
error, // Error or null if initialization failed
reset, // () => void: Clear storage and reinitialize
} = useQuotient();
}
| Field | Type | Description |
|---|---|---|
client | QuotientClient | null | The initialized client instance |
error | Error | null | Set if initialization failed |
reset | () => void | Clear all stored data and reinitialize |
useBlogs
Fetch a paginated list of blogs within a client component. Must be inside a <QuotientProvider>.
| Param | Type | Required | Description |
|---|---|---|---|
page | number | No | Page number |
limit | number | No | Results per page |
statuses | BlogStatus[] | No | Filter by status |
"use client";
import { BlogStatus, useBlogs } from "@quotientjs/react";
export default function BlogList({
page,
limit,
statuses,
}: {
page: number;
limit: number;
statuses: BlogStatus[];
}) {
const { data, isLoading } = useBlogs({
page,
limit,
statuses,
});
const { blogs, pageData } = data;
return (
{/* Render blog list */}
);
}
Common Patterns
User Identification on Login
"use client";
import { useQuotient } from "@quotientjs/react";
function LoginHandler() {
const { client } = useQuotient();
const handleLogin = async (user) => {
await client?.audience.people.upsert({
emailAddress: user.email,
firstName: user.firstName,
lastName: user.lastName,
lists: ["customers"],
});
};
return <button onClick={() => handleLogin(user)}>Login</button>;
}
Marketing Preference Center
"use client";
import { useQuotient } from "@quotientjs/react";
import { useState } from "react";
function EmailPreferences({ userEmail }) {
const [state, setState] = useState("SUBSCRIBED");
const [lists, setLists] = useState(["newsletter", "promotions"]);
const { client } = useQuotient();
const updatePreferences = async () => {
try {
await client.audience.people.upsert({
emailAddress: userEmail,
emailMarketingState: state,
lists: state === "SUBSCRIBED" ? lists : [],
});
toast.success("Preferences updated");
} catch (error) {
toast.error("Failed to update preferences");
}
};
return (
<div>
<label>
<input
type="radio"
checked={state === "SUBSCRIBED"}
onChange={() => setState("SUBSCRIBED")}
/>
Subscribed - Receive marketing emails
</label>
<label>
<input
type="radio"
checked={state === "UNSUBSCRIBED"}
onChange={() => setState("UNSUBSCRIBED")}
/>
Unsubscribed - No marketing emails
</label>
{state === "SUBSCRIBED" && (
<div>
<h3>Email Lists:</h3>
<label>
<input
type="checkbox"
checked={lists.includes("newsletter")}
onChange={(e) => {
if (e.target.checked) {
setLists([...lists, "newsletter"]);
} else {
setLists(lists.filter((l) => l !== "newsletter"));
}
}}
/>
Weekly Newsletter
</label>
{/* More list options... */}
</div>
)}
<button onClick={updatePreferences}>Save Preferences</button>
</div>
);
}