Skip to content

React

Terminal window
npm i @sanwohq/react @sanwohq/paystack
import { SanwoReactProvider } from "@sanwohq/react";
import { paystack } from "@sanwohq/paystack";
export default function App() {
return (
<SanwoReactProvider provider={paystack} publicKey="pk_test_xxxxxxxxxxxx">
<CheckoutPage />
</SanwoReactProvider>
);
}
import { useSanwoCheckout } from "@sanwohq/react";
function CheckoutPage() {
const { checkout, isLoading, error, result, reset } = useSanwoCheckout();
async function pay() {
const res = await checkout({
amount: 500000,
currency: "NGN",
customer: { email: "customer@example.com" },
});
if (res.status === "successful") {
console.log("Paid!", res.reference);
}
}
return (
<button onClick={pay} disabled={isLoading}>
{isLoading ? "Processing…" : "Pay ₦5,000"}
</button>
);
}

Wraps your app (or a subtree) and initializes the Sanwo instance.

<SanwoReactProvider
provider={paystack}
publicKey="pk_test_xxxxxxxxxxxx"
debug={false}
timeout={120}
containerId="checkout-container"
>
{children}
</SanwoReactProvider>
Prop Type Required Default Description
provider SanwoProvider Yes — Imported provider
publicKey string Yes — Your provider public key
debug boolean No false Enable debug logging
timeout number No 120 Checkout timeout in seconds
containerId string No — Render checkout into a specific DOM element

The primary hook for triggering payments.

const { checkout, isLoading, error, result, reset } = useSanwoCheckout();
Value Type Description
checkout (options: CheckoutOptions) => Promise<CheckoutResult> Start a checkout
isLoading boolean true while checkout is in progress
error Error | null Set if checkout threw
result CheckoutResult | null Last checkout result
reset () => void Clear error and result

Low-level hook for direct access to the Sanwo instance.

const { sanwo, providerId, state } = useSanwo();
Value Type Description
sanwo SanwoInstance The raw callable instance
providerId string Current provider identifier
state string Current checkout state

Use this when you need event listeners or manual control:

const { sanwo } = useSanwo();
useEffect(() => {
const unsub = sanwo.on("success", (data) => {
analytics.track("payment_success", { ref: data.reference });
});
return unsub;
}, [sanwo]);

A ready-made button component that handles checkout state for you.

import { SanwoButton } from "@sanwohq/react";
<SanwoButton
checkoutOptions={{
amount: 500000,
currency: "NGN",
customer: { email: "customer@example.com" },
}}
onSuccess={(result) => console.log("Paid!", result.reference)}
onError={(err) => console.error(err)}
loadingText="Processing…"
>
Pay ₦5,000
</SanwoButton>
Prop Type Required Description
checkoutOptions CheckoutOptions Yes What to charge
onSuccess (result) => void No Called on successful payment
onError (error) => void No Called on failure
loadingText string No Button text while loading
children ReactNode No Button content

All other props are forwarded to the underlying <button> element.

import { SanwoReactProvider, SanwoButton } from "@sanwohq/react";
import { paystack } from "@sanwohq/paystack";
function App() {
return (
<SanwoReactProvider provider={paystack} publicKey="pk_test_xxxxxxxxxxxx">
<h1>My Store</h1>
<SanwoButton
checkoutOptions={{
amount: 500000,
currency: "NGN",
customer: { email: "customer@example.com" },
reference: `order_${Date.now()}`,
}}
onSuccess={(result) => {
window.location.href = `/receipt?ref=${result.reference}`;
}}
onError={(err) => alert(err.message)}
loadingText="Processing…"
className="pay-btn"
>
Pay ₦5,000
</SanwoButton>
</SanwoReactProvider>
);
}

SanwoReactProvider uses React context, so it must live in a client component.

"use client";
import { SanwoReactProvider } from "@sanwohq/react";
import { paystack } from "@sanwohq/paystack";
export function Providers({ children }: { children: React.ReactNode }) {
return (
<SanwoReactProvider provider={paystack} publicKey="pk_test_xxxxxxxxxxxx">
{children}
</SanwoReactProvider>
);
}