useConsent React hook in TypeScript
v1.0.0Added in 1.0.0
A React cookie consent hook: which categories a visitor allowed, when and under which policy version, shared by banner, links and scripts.
Press Accept all or Reject all, or flip the categories and press Save choices: the record (method, time, choices) and the Google Consent Mode values update, and the video embed loads only once Marketing is allowed. Reset forgets the decision. Raise the policy version in the playground and the stored choice no longer counts, so the site would ask again. The choice survives a reload and, with local storage, follows you to other tabs.
useConsent is a Pro React hook in the React hooks and utilities category, written in TypeScript for React 19. It installs as source with npx wingo-ui@latest add use-consent, together with usePersistedState.
Add to a project
Requirements: React 19, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup
npx wingo-ui@latest add use-consentuseConsent is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans
Usage
Import useConsent from @/hooks/use-consent.
import { useConsent } from "@/hooks/use-consent"
export function YoutubeEmbed({ id }: { id: string }) {
const { hydrated, has, save, choices } = useConsent()
if (!hydrated) return null
if (!has("marketing"))
return (
<button type="button" onClick={() => save({ ...choices, marketing: true })}>
Allow marketing cookies to watch the video
</button>
)
return <iframe title="Northwind CRM tour" src={`https://www.youtube-nocookie.com/embed/${id}`} />
}API
versiondefault1numberThe policy version. Bump it when the categories or the policy change: records made under another version count as undecided.
storagedefault"cookie""cookie" | "local" | "session"Where the record lives. A cookie can be read on the server too (render nothing consent-dependent on the first paint when it is missing).
maxAgeDaysdefault180numberHow long a cookie choice is kept before the visitor is asked again.
storageKeydefault"ui-consent"stringCookie / storage key. Every hook with the same key shares one record.
categoriesreadonly string[]The category ids the site uses, default ["necessary", "preferences", "analytics", "marketing"]. necessary is always true.
useConsent(options?) => { record: ConsentRecord | null; decided; hydrated; choices; has(category); acceptAll(); rejectAll(); save(choices); reset() }record is { version, choices, decidedAt (ISO), method: accept-all | reject-all | custom } or null while undecided. hydrated is false on the server and during hydration: show the banner only once it is true and decided is false, so it never flashes for people who already chose.
Parts
getConsent
functionThe same record outside React (a script loader, an analytics wrapper). Null on the server. Signature: (options?) => ConsentRecord | null.
hasConsent
functionThe same record outside React (a script loader, an analytics wrapper). Null on the server. Signature: (category, options?) => boolean.
setConsent
functionWrite a record outside React, and run code after every decision (load analytics when allowed, remove cookies when withdrawn). Signature: (record | null, options?) => void.
onConsentChange
functionWrite a record outside React, and run code after every decision (load analytics when allowed, remove cookies when withdrawn). Signature: (listener: (record, key) => void) => () => void.
openConsentSettings
functionA "Cookie settings" link anywhere calls openConsentSettings(); the consent component listens with useConsentSettingsRequest and opens its settings. Signature: (storageKey?) => void.
useConsentSettingsRequest
hookA "Cookie settings" link anywhere calls openConsentSettings(); the consent component listens with useConsentSettingsRequest and opens its settings. Signature: (handler: () => void, storageKey?) => void.
toGoogleConsentMode
functionGoogle Consent Mode v2 values for gtag("consent", "update", ...): analytics → analytics_storage, marketing → the three ad signals, preferences → functionality and personalization. Signature: (choices) => Record<string, "granted" | "denied">.
normalizeConsent
functionEvery category present with necessary forced on; the default ids and key. Signature: (choices, categories?) => ConsentChoices.
DEFAULT_CONSENT_CATEGORIES
constantEvery category present with necessary forced on; the default ids and key. Type: readonly string[].
DEFAULT_CONSENT_KEY
constantEvery category present with necessary forced on; the default ids and key. Type: string.
Examples
Consent-gated video
has("marketing") decides between the embed and a placeholder; allowing it saves a custom record for this session only.
Dependencies
Files
- hooks/use-consent.ts
FAQ
Is the useConsent hook free?
The preview, props and docs are free; copying the source needs a Pro plan. See plans.
How do I install useConsent?
Run npx wingo-ui@latest add use-consent. It also adds the Wingo UI item it builds on (usePersistedState). With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/use-consent.
See also
Used in
More React hooks and utilities
Articles using this component
- Nextjs Cookie Consent: GDPR Banner and Consent Mode v2
Next.js and Tailwind CSS12 min read