Documentation
Documentation
Replace useConsentManager()
useConsentManager() returned the whole consent state, so every component
that called it re-rendered on every change. v3 has one hook per field. Run the
codemod first:
Review the proposed files, then run it again without --dry-run. For this v2
component:
the codemod writes:
The codemod keeps the entry you imported from. Change @c15t/react to
c15t/react afterwards if you moved to the umbrella package. Fields it cannot
rewrite stay on a useConsentManager() call under a TODO(c15t v3) comment,
which fails the build until you replace them. The table lists the v2 fields
components read. The other fields held provider configuration, such as
legalLinks, scripts and storageConfig, or store internals; set
configuration through ConsentProvider props.
Import hooks from c15t/react, c15t/next or c15t/tanstack-start, and
useHeadlessConsentUI from the matching /headless entry.
| v2 field | v3 replacement |
|---|---|
activeUI | useActiveUI(). It returns null until c15t picks a surface, where v2 returned 'none'. |
setActiveUI(ui) | useSetActiveUI() |
has(category) | useConsent(category), one call per category at the top of the component |
consents | useConsents() |
saveConsents('all') | useHeadlessConsentUI().saveCustomPreferences('all') |
saveConsents('necessary') | useHeadlessConsentUI().saveCustomPreferences('none') |
saveConsents('custom') | useConsentDraft().save(), or useHeadlessConsentUI().saveCustomPreferences() inside a ConsentDraftProvider |
selectedConsents | useConsentDraft().values |
setSelectedConsent(name, value) | useConsentDraft().set(name, value) |
setConsent(name, value) | useSaveConsents(), called with { [name]: value } |
consentInfo | useExplicitChoice() |
hasConsented() | useExplicitChoice() !== null |
consentCategories, consentTypes, getDisplayedConsents() | useConsentDraft().displayedCategories, with labels from useTranslations().consentTypes |
policyCategories | usePolicyCategories(). The v2 list started with 'necessary'; this one does not. |
policyScopeMode | usePolicyScopeMode() |
policyBanner | usePromptPresentation() |
policyDialog | usePreferencesPresentation() |
model | useModel(). It returns null while no policy matches, where v2 returned 'opt-in'. |
branding | useBranding(). It returns null when unset, where v2 returned 'c15t'. |
iab | useIABSnapshot() |
locationInfo | useLocation() |
overrides, setOverrides() | useOverrides(), useSetOverrides() |
setLanguage() | useSetLanguage() |
user, identifyUser() | useUser(), useIdentify() |
translationConfig | useTranslations() for the active strings |
subscribeToConsentChanges(listener) | useSubscribeToConsentChanges(), or the onPermissionsChanged callback |
updateConsentCategories(categories) | useRegisterConsentCategories() |
manager | Nothing. Use the hooks above. |
saveCustomPreferences() saves the way the stock buttons do. It closes the
banner or dialog after a successful save. useSaveConsents() calls the engine
directly and does not close anything.
In v2, useConsentManager() kept one draft per component. In v3,
useConsentDraft() and useHeadlessConsentUI() share a draft only inside a
ConsentDraftProvider. Without one, saveCustomPreferences() saves a fresh
draft and ignores what useConsentDraft().set() staged, even in the same
component. Save with useConsentDraft().save(), or render the code that stages
and the code that saves inside one ConsentDraftProvider. ConsentWidget
already includes one. The codemod
adds a TODO(c15t v3) comment where this applies.