---
id: 05-core-consent-react
epic: dsr-consent-and-cookie-banner
title: core-consent React subpath — ConsentProvider + useConsent()
type: technical-story
status: done
feature: core-consent
depends-on: [04-core-consent-implementation]
blocks: [09-cookie-consent-banner]
created: 2026-05-19T12:00:00Z
updated: 2026-05-19T19:21:30.198Z
---

## Goal

Add the React subpath `core-consent/react` exporting `<ConsentProvider>` and `useConsent()`, following the pattern established by `@repo/core-analytics/react` (`<AnalyticsProvider>` + `useAnalytics()`).

## Why

The `<CookieConsentBanner>` component (Story 09) reads consent state and dispatches grant/withdraw via `useConsent()`. The React subpath must exist and be stable before the banner can be built.

## Done when

- `packages/core-consent/src/react/index.ts` exports `<ConsentProvider>` + `useConsent()`.
- `<ConsentProvider>` accepts an `IConsent` instance as a prop and makes it available via context.
- `useConsent()` returns `{ isGranted, grant, withdraw, getCategories }` bound to the context instance.
- The subpath is exposed via `package.json` exports as `"./react"`.
- Tests using React Testing Library assert: `useConsent()` returns the methods; `grant()` and `withdraw()` propagate to the injected `IConsent`; `isGranted()` reflects the mock instance's state; missing `<ConsentProvider>` ancestor throws a descriptive error.
- `pnpm typecheck && pnpm lint && pnpm test && pnpm conformance && pnpm fallow:audit && pnpm coverage:diff` all pass.

## In scope

- `packages/core-consent/src/react/consent-provider.tsx` + `use-consent.ts`.
- `packages/core-consent/src/react/index.ts` barrel.
- `package.json` exports `"./react"` subpath entry.
- RTL + vitest unit tests.

## Out of scope

- `<CookieConsentBanner>` component (Story 09).
- Any cookie read/write logic (lives in the banner, not the hook).
- SSR placeholder / dynamic-import loader (documented in consent.md, Story 11; the hook itself is client-only by design — no SSR surface here).

## Tasks

- [x] Add `<ConsentProvider>` + `useConsent()` hook in `packages/core-consent/src/react/` + barrel export + `"./react"` subpath in `package.json`; RTL tests asserting context propagation, method delegation, and missing-provider error; all gates pass.
