- Overview
- Installation
- Getting Started
- API Reference
- Components
- Hooks
- Core Services
- Type Definitions
- Internationalization
- Utilities
- Usage Examples
- Best Practices
- Troubleshooting
- Architecture
The TruConsent React Native SDK is a comprehensive solution for displaying and managing consent banners in React Native applications. It provides a native mobile UI for collecting user consent, supporting GDPR, CCPA, and other privacy regulations.
- Native React Native Components: Built specifically for mobile applications
- Multiple Consent Types: Supports standard consent, cookie consent, and general consent
- Flexible Purpose Management: Users can accept/decline individual purposes or use bulk actions
- Internationalization: Built-in support for multiple languages (English, Hindi, Tamil)
- TypeScript Support: Full TypeScript definitions for type safety
- Customizable UI: Modern, mobile-friendly interface with customizable branding
- Consent Tracking: Automatic logging of consent actions to the TruConsent API
- Rights Center: Comprehensive rights management interface (RightCenter component) with WebView integration
- Error Handling: Comprehensive error handling with user-friendly messages
- React Hooks: Custom hooks (useBanner, useConsent) for flexible integration
- React Native 0.70.0+
- iOS
- Android
- Expo (with compatible versions)
- React >= 18.0.0
- React Native >= 0.70.0
- Node.js >= 16.0.0
npm install @truconsent/consent-banner-react-native
# or
yarn add @truconsent/consent-banner-react-nativenpm install react react-native react-i18next i18next
# or
yarn add react react-native react-i18next i18nextIf you're using Expo, ensure your app.json includes the necessary configuration:
{
"expo": {
"extra": {
"truConsentApiKey": "your-api-key",
"truConsentOrganizationId": "your-org-id"
}
}
}import React from 'react';
import { TruConsentModal } from '@truconsent/consent-banner-react-native';
function App() {
const handleConsentClose = (action) => {
console.log('User consent action:', action);
// Handle consent action (approved, declined, partial_consent, etc.)
};
return (
<TruConsentModal
apiKey="your-api-key"
organizationId="your-org-id"
bannerId="your-banner-id"
userId="user-123"
onClose={handleConsentClose}
companyName="Your Company"
logoUrl="https://example.com/logo.png"
/>
);
}import React, { useState } from 'react';
import { TruConsentModal } from '@truconsent/consent-banner-react-native';
function MyForm() {
const [showConsent, setShowConsent] = useState(false);
const handleConsentClose = (action) => {
if (action === 'approved') {
// Proceed with form submission
console.log('Consent approved, submitting form...');
} else {
// Show error or prevent submission
console.log('Consent not provided');
}
setShowConsent(false);
};
const handleSubmit = () => {
// Show consent modal before submitting
setShowConsent(true);
};
return (
<>
<button onPress={handleSubmit}>Submit Form</button>
{showConsent && (
<TruConsentModal
apiKey="your-api-key"
organizationId="your-org-id"
bannerId="your-banner-id"
userId="user-123"
onClose={handleConsentClose}
/>
)}
</>
);
}The SDK exports the following:
// Main Components
export { TruConsentModal } from './components/TruConsentModal';
export { TruConsent } from './components/TruConsent';
export { BannerUI } from './components/BannerUI';
export { CookieBannerUI } from './components/CookieBannerUI';
export { RightCenter } from './components/RightCenter';
// Hooks
export { useBanner } from './hooks/useBanner';
export { useConsent } from './hooks/useConsent';
// Core Services
export { fetchBanner, submitConsent } from './core/BannerService';
export * from './core/ConsentManager';
// Types
export * from './core/types';
// Utilities
export { generateRequestId, isValidUUID } from './utils/RequestIdGenerator';The main component for displaying consent banners in a modal overlay.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
apiKey |
string |
Yes | - | API key for authentication with TruConsent API |
organizationId |
string |
Yes | - | Organization identifier |
bannerId |
string |
Yes | - | Banner/Collection Point ID to display |
userId |
string |
Yes | - | Unique user identifier for consent tracking |
apiUrl |
string |
No | TruAPI root URL for consent + banners endpoints | |
logoUrl |
string |
No | - | URL of the company logo to display in the banner |
companyName |
string |
No | 'Mars Company' |
Company name to display in the banner |
onClose |
(action: ConsentAction) => void |
No | - | Callback function called when the modal closes. Receives the consent action type. |
'approved': User accepted all purposes'declined': User declined all purposes'partial_consent': User accepted some but not all purposes'revoked': User revoked previously given consent'no_action': User closed the modal without taking action
<TruConsentModal
apiKey="abc123xyz"
organizationId="org-123"
bannerId="banner-456"
userId="user-789"
companyName="Acme Corp"
logoUrl="https://acme.com/logo.png"
onClose={(action) => {
console.log('Consent action:', action);
}}
/>- Automatically fetches banner configuration from the API on mount
- Manages consent state internally using React hooks
- Automatically submits consent to the API when user takes action
- Handles loading states and error conditions
- Supports both standard consent and cookie consent types
A wrapper component that provides web SDK parity. It's an alias for TruConsentModal.
import { TruConsent } from '@truconsent/consent-banner-react-native';
// Same props as TruConsentModal
<TruConsent {...props} />Internal component for rendering standard consent banners. Typically used internally by TruConsentModal, but can be used directly for custom implementations.
Internal component for rendering cookie consent banners. Used when banner.consent_type === 'cookie_consent'.
Internal component for rendering right center positioning. Used for specific banner layouts.
Custom hook for fetching banner data from the API.
function useBanner(config: FetchBannerConfig | null): UseBannerResultinterface FetchBannerConfig {
bannerId: string;
apiKey: string;
organizationId: string;
apiUrl?: string;
}interface UseBannerResult {
banner: Banner | null;
isLoading: boolean;
error: string | null;
refetch: () => void;
}import { useBanner } from '@truconsent/consent-banner-react-native';
function MyComponent() {
const { banner, isLoading, error, refetch } = useBanner({
bannerId: 'banner-123',
apiKey: 'api-key',
organizationId: 'org-123',
});
if (isLoading) return <Text>Loading...</Text>;
if (error) return <Text>Error: {error}</Text>;
if (!banner) return <Text>No banner found</Text>;
return <Text>Banner: {banner.title}</Text>;
}Custom hook for managing consent state for purposes.
function useConsent(initialPurposes: Purpose[]): UseConsentResultinitialPurposes: Array ofPurposeobjects to initialize the consent state
interface UseConsentResult {
purposes: Purpose[];
updatePurpose: (purposeId: string, status: 'accepted' | 'declined') => void;
acceptAll: () => void;
rejectAll: () => void;
acceptSelected: () => Purpose[];
setPurposes: (purposes: Purpose[]) => void;
}updatePurpose(purposeId, status): Update a single purpose's consent statusacceptAll(): Accept all purposesrejectAll(): Reject all optional purposes (mandatory purposes remain accepted)acceptSelected(): Accept only selected purposes and all mandatory purposes. Returns the updated purposes array.setPurposes(purposes): Replace the entire purposes array
import { useConsent } from '@truconsent/consent-banner-react-native';
function ConsentManager({ initialPurposes }) {
const {
purposes,
updatePurpose,
acceptAll,
rejectAll,
acceptSelected,
} = useConsent(initialPurposes);
return (
<View>
{purposes.map((purpose) => (
<TouchableOpacity
key={purpose.id}
onPress={() =>
updatePurpose(
purpose.id,
purpose.consented === 'accepted' ? 'declined' : 'accepted'
)
}
>
<Text>{purpose.name}</Text>
</TouchableOpacity>
))}
<Button onPress={acceptAll} title="Accept All" />
<Button onPress={rejectAll} title="Reject All" />
</View>
);
}Service for making API calls to the TruConsent backend.
Fetches banner configuration from the API.
async function fetchBanner(config: FetchBannerConfig): Promise<Banner>Parameters:
config.bannerId: Banner ID to fetchconfig.apiKey: API key for authenticationconfig.organizationId: Organization IDconfig.apiUrl: TruAPI root URL (e.g.https://api-dev.truconsent.io)
Returns: Promise resolving to a Banner object
Throws:
Error('Missing bannerId')if bannerId is not providedError('Missing apiKey')if apiKey is not providedError('Missing organizationId')if organizationId is not providedError('Authentication required')on 401 statusError('Access forbidden')on 403 statusError('Banner not found')on 404 status- Other errors for other HTTP failures
Example:
import { fetchBanner } from '@truconsent/consent-banner-react-native';
try {
const banner = await fetchBanner({
bannerId: 'banner-123',
apiKey: 'api-key',
organizationId: 'org-123',
});
console.log('Banner loaded:', banner);
} catch (error) {
console.error('Failed to load banner:', error.message);
}Submits user consent to the API.
async function submitConsent(config: SubmitConsentConfig): Promise<any>Parameters:
config.collectionPointId: Collection point ID from the bannerconfig.userId: User identifierconfig.purposes: Array of purpose objects with consent statusconfig.action: Consent action type ('approved','declined', etc.)config.apiKey: API key for authenticationconfig.organizationId: Organization IDconfig.requestId: Optional request ID for trackingconfig.apiUrl: TruAPI root URL
Returns: Promise resolving to API response
Throws:
Error('Missing collectionPointId')if collectionPointId is not providedError('Missing apiKey')if apiKey is not providedError('Missing organizationId')if organizationId is not providedError('Failed to submit consent')on HTTP failure
Example:
import { submitConsent } from '@truconsent/consent-banner-react-native';
try {
await submitConsent({
collectionPointId: 'cp-123',
userId: 'user-456',
purposes: [
{ id: 'p1', consented: 'accepted', ... },
{ id: 'p2', consented: 'declined', ... },
],
action: 'approved',
apiKey: 'api-key',
organizationId: 'org-123',
});
console.log('Consent submitted successfully');
} catch (error) {
console.error('Failed to submit consent:', error.message);
}Utility functions for managing consent state.
Updates a single purpose's consent status in an array.
function updatePurposeStatus(
purposes: Purpose[],
purposeId: string,
newStatus: 'accepted' | 'declined'
): Purpose[]Automatically accepts all mandatory purposes while preserving user selections for optional ones.
function acceptMandatoryPurposes(purposes: Purpose[]): Purpose[]Determines the overall consent action based on purpose states.
function determineConsentAction(
purposes: Purpose[],
previousPurposes?: Purpose[] | null
): ConsentActionReturns:
'approved': All purposes accepted'declined': All purposes declined'partial_consent': Mixed consent (some accepted, some declined)'revoked': Previously accepted purposes were declined
Returns all purposes with accepted consent.
function getAcceptedPurposes(purposes: Purpose[]): Purpose[]Returns all purposes with declined consent.
function getDeclinedPurposes(purposes: Purpose[]): Purpose[]Checks if any optional (non-mandatory) purposes are accepted.
function hasOptionalAccepted(purposes: Purpose[]): booleanChecks if there are any mandatory purposes.
function hasMandatoryPurposes(purposes: Purpose[]): booleanMain banner configuration object returned from the API.
interface Banner {
banner_id: string;
collection_point: string;
version?: string;
title: string;
name?: string; // Alternative field name from API
expiry_type?: string;
asset?: Asset;
purposes: Purpose[];
data_elements?: DataElement[];
legal_entities?: LegalEntity[];
tools?: Tool[];
processing_activities?: ProcessingActivity[];
consent_type?: 'standard_consent' | 'cookie_consent' | 'general';
cookie_config?: CookieConfig;
banner_settings?: BannerSettings;
organization?: Organization;
organization_name?: string;
cookie_data_elements?: DataElement[];
show_purposes?: boolean;
}Represents a consent purpose that users can accept or decline.
interface Purpose {
id: string;
name: string;
description: string;
is_mandatory: boolean;
consented: 'accepted' | 'declined' | 'pending';
expiry_period: string;
expiry_label?: string;
data_elements?: DataElement[];
processing_activities?: ProcessingActivity[];
legal_entities?: LegalEntity[];
tools?: Tool[];
}Represents a data element associated with a purpose.
interface DataElement {
id: string;
name: string;
description?: string;
display_id?: string;
}Represents a legal entity involved in data processing.
interface LegalEntity {
id: string;
name: string;
description?: string;
display_id?: string;
}Represents a tool used for data processing.
interface Tool {
id: string;
name: string;
description?: string;
display_id?: string;
}Represents a processing activity.
interface ProcessingActivity {
id: string;
name: string;
description?: string;
display_id?: string;
}Represents an asset associated with the banner.
interface Asset {
id: string;
name: string;
description?: string;
asset_type?: string;
}Configuration for cookie consent banners.
interface CookieConfig {
cookies?: Cookie[];
selected_data_element_ids?: string[];
selected_processing_activity_ids?: string[];
}Cookie information for cookie consent.
interface Cookie {
id?: string;
name?: string;
category?: string;
domain?: string;
expiry?: string;
}UI customization settings for the banner.
interface BannerSettings {
font_type?: string;
font_size?: string;
primary_color?: string;
secondary_color?: string;
action_button_text?: string;
warning_text?: string;
logo_url?: string;
banner_title?: string;
disclaimer_text?: string;
footer_text?: string;
show_purposes?: boolean;
}Organization information.
interface Organization {
name: string;
legal_name?: string;
trade_name?: string;
logo_url?: string;
}Type representing possible consent actions.
type ConsentAction =
| 'approved'
| 'declined'
| 'no_action'
| 'revoked'
| 'partial_consent';Request object for submitting consent.
interface ConsentRequest {
userId: string;
purposes: Purpose[];
action: ConsentAction;
requestId?: string;
}Configuration object for TruConsent components.
interface TruConsentConfig {
apiKey: string;
organizationId: string;
bannerId: string;
userId: string;
apiUrl?: string;
logoUrl?: string;
companyName?: string;
onClose?: (action: ConsentAction) => void;
}The SDK includes built-in internationalization support using i18next and react-i18next.
- English (
en) - Default - Hindi (
hi) - Tamil (
ta)
The SDK uses the following translation keys:
{
"consent_by": "Consent by {{companyName}}",
"decline_rights": "You have the right to decline consents which you feel are not required by {{companyName}}",
"expiry_type": "Expiry Type: {{expiry}}",
"accept": "Accept",
"reject_all": "Reject All",
"accept_all": "Accept All",
"accept_only_necessary": "Accept Only Necessary",
"accept_selected": "Accept Selected",
"i_consent": "I Consent",
"mandatory": "Mandatory",
"data_elements": "Data Elements",
"legal_entities": "Legal Entities",
"tools": "Tools",
"processing_activities": "Processing Activities",
"data_processors": "Data Processors"
}To add custom translations or modify existing ones, you can extend the i18n configuration:
import i18n from '@truconsent/consent-banner-react-native/utils/i18n';
// Add custom translations
i18n.addResourceBundle('en', 'translation', {
'custom_key': 'Custom Value',
}, true, true);
// Change language
i18n.changeLanguage('hi'); // Switch to HindiTranslation files are located at:
src/utils/locales/en.jsonsrc/utils/locales/hi.jsonsrc/utils/locales/ta.json
Utility for generating unique request IDs for consent tracking.
Generates a unique UUID v4 request ID.
function generateRequestId(): stringReturns: A UUID v4 string (e.g., "550e8400-e29b-41d4-a716-446655440000")
Implementation:
- Uses
crypto.randomUUID()if available (React Native 0.70+) - Falls back to manual UUID v4 generation for older versions
Example:
import { generateRequestId } from '@truconsent/consent-banner-react-native';
const requestId = generateRequestId();
console.log(requestId); // "550e8400-e29b-41d4-a716-446655440000"Validates if a string is a valid UUID format.
function isValidUUID(str: string): booleanExample:
import { isValidUUID } from '@truconsent/consent-banner-react-native';
isValidUUID('550e8400-e29b-41d4-a716-446655440000'); // true
isValidUUID('invalid-id'); // falseimport React, { useState } from 'react';
import { View, Button } from 'react-native';
import { TruConsentModal } from '@truconsent/consent-banner-react-native';
function App() {
const [showConsent, setShowConsent] = useState(false);
const handleConsentClose = (action) => {
console.log('Consent action:', action);
setShowConsent(false);
if (action === 'approved') {
// Proceed with application logic
console.log('User consented, proceeding...');
} else {
// Handle declined consent
console.log('User declined consent');
}
};
return (
<View>
<Button
title="Show Consent"
onPress={() => setShowConsent(true)}
/>
{showConsent && (
<TruConsentModal
apiKey="your-api-key"
organizationId="your-org-id"
bannerId="your-banner-id"
userId="user-123"
onClose={handleConsentClose}
/>
)}
</View>
);
}import React, { useState } from 'react';
import { View, TextInput, Button } from 'react-native';
import { TruConsentModal } from '@truconsent/consent-banner-react-native';
import type { ConsentAction } from '@truconsent/consent-banner-react-native';
function RegistrationForm() {
const [formData, setFormData] = useState({ name: '', email: '' });
const [showConsent, setShowConsent] = useState(false);
const [canSubmit, setCanSubmit] = useState(false);
const handleSubmit = () => {
// Show consent before submitting
setShowConsent(true);
};
const handleConsentClose = async (action: ConsentAction) => {
setShowConsent(false);
if (action === 'approved') {
// Submit form after consent
try {
await submitForm(formData);
console.log('Form submitted successfully');
setCanSubmit(true);
} catch (error) {
console.error('Form submission failed:', error);
}
} else {
alert('Please provide consent to proceed');
}
};
return (
<View>
<TextInput
placeholder="Name"
value={formData.name}
onChangeText={(text) => setFormData({ ...formData, name: text })}
/>
<TextInput
placeholder="Email"
value={formData.email}
onChangeText={(text) => setFormData({ ...formData, email: text })}
/>
<Button title="Submit" onPress={handleSubmit} />
{showConsent && (
<TruConsentModal
apiKey="your-api-key"
organizationId="your-org-id"
bannerId="your-banner-id"
userId="user-123"
onClose={handleConsentClose}
/>
)}
</View>
);
}import React from 'react';
import { View, Text, ActivityIndicator } from 'react-native';
import { useBanner, useConsent } from '@truconsent/consent-banner-react-native';
function CustomConsentBanner() {
const { banner, isLoading, error } = useBanner({
bannerId: 'banner-123',
apiKey: 'api-key',
organizationId: 'org-123',
});
const { purposes, acceptAll, rejectAll, updatePurpose } = useConsent(
banner?.purposes || []
);
if (isLoading) {
return <ActivityIndicator />;
}
if (error) {
return <Text>Error: {error}</Text>;
}
if (!banner) {
return <Text>No banner found</Text>;
}
return (
<View>
<Text>{banner.title}</Text>
{purposes.map((purpose) => (
<View key={purpose.id}>
<Text>{purpose.name}</Text>
<Button
title={purpose.consented === 'accepted' ? 'Decline' : 'Accept'}
onPress={() =>
updatePurpose(
purpose.id,
purpose.consented === 'accepted' ? 'declined' : 'accepted'
)
}
/>
</View>
))}
<Button title="Accept All" onPress={acceptAll} />
<Button title="Reject All" onPress={rejectAll} />
</View>
);
}import React, { useState } from 'react';
import { TruConsentModal } from '@truconsent/consent-banner-react-native';
import type { ConsentAction } from '@truconsent/consent-banner-react-native';
function ConsentHandler() {
const [showConsent, setShowConsent] = useState(false);
const handleConsentClose = (action: ConsentAction) => {
setShowConsent(false);
switch (action) {
case 'approved':
console.log('Full consent granted');
// Enable all features
break;
case 'declined':
console.log('Consent declined');
// Disable features requiring consent
break;
case 'partial_consent':
console.log('Partial consent granted');
// Enable only features for accepted purposes
break;
case 'revoked':
console.log('Consent revoked');
// Disable all features
break;
case 'no_action':
console.log('No action taken');
// Keep current state
break;
default:
console.log('Unknown action:', action);
}
};
return (
<>
<Button title="Show Consent" onPress={() => setShowConsent(true)} />
{showConsent && (
<TruConsentModal
apiKey="your-api-key"
organizationId="your-org-id"
bannerId="your-banner-id"
userId="user-123"
onClose={handleConsentClose}
/>
)}
</>
);
}import { TruConsentModal } from '@truconsent/consent-banner-react-native';
function App() {
return (
<TruConsentModal
apiKey="your-api-key"
organizationId="your-org-id"
bannerId="your-banner-id"
userId="user-123"
apiUrl="https://custom-api.example.com"
onClose={(action) => console.log(action)}
/>
);
}Always handle errors gracefully:
const handleConsentClose = (action: ConsentAction) => {
try {
if (action === 'approved') {
// Proceed with logic
}
} catch (error) {
console.error('Error handling consent:', error);
// Show user-friendly error message
}
};Use consistent user IDs for proper consent tracking:
// Good: Use consistent user ID
const userId = user?.id || guestId || 'anonymous';
// Bad: Using random IDs each time
const userId = Math.random().toString();Only show the consent modal when needed:
// Good: Conditional rendering
{showConsent && (
<TruConsentModal {...props} />
)}
// Bad: Always rendering (wastes resources)
<TruConsentModal {...props} visible={showConsent} />Show loading indicators while consent is being processed:
const [isProcessing, setIsProcessing] = useState(false);
const handleConsentClose = async (action: ConsentAction) => {
setIsProcessing(true);
try {
// Process consent
await processConsent(action);
} finally {
setIsProcessing(false);
}
};Store consent status locally to avoid showing the banner repeatedly:
import AsyncStorage from '@react-native-async-storage/async-storage';
const CONSENT_KEY = 'user_consent_status';
// Check if consent already given
const hasConsent = await AsyncStorage.getItem(CONSENT_KEY);
if (!hasConsent) {
setShowConsent(true);
}
// Store consent after approval
const handleConsentClose = async (action: ConsentAction) => {
if (action === 'approved') {
await AsyncStorage.setItem(CONSENT_KEY, 'true');
}
};CRITICAL: When wrapping TruConsentModal in your own component, ensure all hooks are called before any conditional returns:
// Good: All hooks before conditional return
function MyConsentWrapper({ visible }) {
const [state, setState] = useState(false);
const memoized = useMemo(() => compute(), []);
if (!visible) return null; // OK: hooks already called
return <TruConsentModal {...props} />;
}
// Bad: Conditional return before hooks
function MyConsentWrapper({ visible }) {
if (!visible) return null; // BAD: hooks not called yet
const [state, setState] = useState(false); // This will cause errors
return <TruConsentModal {...props} />;
}Never hardcode API keys in your source code. Use environment variables or secure storage:
// Good: Using environment variables
const apiKey = process.env.TRU_CONSENT_API_KEY;
// Bad: Hardcoded keys
const apiKey = 'abc123xyz'; // Never do thisCause: Conditional rendering of TruConsentModal or hooks called after conditional returns.
Solution: Ensure all hooks are called before any conditional returns in your wrapper component.
// Fix: Call all hooks first
function Wrapper({ visible }) {
const [state, setState] = useState(false); // Hook called first
if (!visible) return null; // Conditional return after hooks
return <TruConsentModal {...props} />;
}Cause: Invalid banner ID or API credentials.
Solutions:
- Verify the
bannerIdis correct - Check that the
apiKeyandorganizationIdare valid - Ensure the banner exists in your TruConsent dashboard
- Verify API base URL is correct
Cause: Invalid or missing API key.
Solutions:
- Verify your API key is correct
- Check that the API key hasn't expired
- Ensure the API key has proper permissions
- Verify the
organizationIdmatches the API key
Cause: Component not mounted or visible state issue.
Solutions:
- Ensure the component is conditionally rendered correctly
- Check that all required props are provided
- Verify the component is in the component tree
- Check for console errors
Cause: Network issues or API errors.
Solutions:
- Check network connectivity
- Verify API endpoint is accessible
- Check console for error messages
- Verify request payload is correct
Cause: Missing type definitions or incorrect types.
Solutions:
- Ensure TypeScript is properly configured
- Import types from the SDK:
import type { ConsentAction } from '@truconsent/consent-banner-react-native' - Check that all required props have correct types
Enable debug logging by checking console output. The SDK logs:
- Banner loading state
- API requests and responses
- Consent actions
- Errors
- Check console logs for error messages
- Verify all required props are provided
- Test with a simple example first
- Check the API credentials in TruConsent dashboard
- Review the network requests in React Native debugger
TruConsentModal (Main Component)
├── useBanner (Hook) - Fetches banner data
├── useConsent (Hook) - Manages consent state
├── BannerUI (Component) - Renders standard consent
├── CookieBannerUI (Component) - Renders cookie consent
└── Modal (React Native) - Provides modal overlay
1. Component Mounts
↓
2. useBanner fetches banner configuration
↓
3. Banner data loaded → useConsent initializes
↓
4. User interacts with banner
↓
5. useConsent updates purpose states
↓
6. User clicks action button
↓
7. submitConsent sends data to API
↓
8. onClose callback fired with action type
↓
9. Component unmounts or hides
TruConsentModal
├── useState (visible, actionLoading, error, requestId)
├── useRef (actionTakenRef, actionRunningRef, closeButtonClickedRef)
├── useBanner (banner, isLoading, bannerError)
├── useConsent (purposes, updatePurpose, acceptAll, rejectAll, acceptSelected)
└── useEffect (4 hooks for logging, cleanup, and state management)
src/
├── components/
│ ├── TruConsentModal.tsx # Main modal component
│ ├── TruConsent.tsx # Web parity wrapper
│ ├── BannerUI.tsx # Standard consent UI
│ ├── CookieBannerUI.tsx # Cookie consent UI
│ └── ... # Supporting components
├── hooks/
│ ├── useBanner.ts # Banner fetching hook
│ └── useConsent.ts # Consent state hook
├── core/
│ ├── BannerService.ts # API client
│ ├── ConsentManager.ts # Consent utilities
│ └── types.ts # TypeScript definitions
└── utils/
├── i18n.ts # Internationalization
├── RequestIdGenerator.ts # UUID generation
└── locales/ # Translation files
The SDK uses React hooks for state management:
- Local State:
useStatefor component-specific state - Custom Hooks:
useBanneranduseConsentfor complex state logic - Refs:
useReffor values that don't trigger re-renders
The SDK communicates with the TruConsent API using:
- fetch API: Native React Native fetch for HTTP requests
- Headers: API key and organization ID in request headers
- Error Handling: Comprehensive error messages for different HTTP status codes
MIT
For issues, questions, or contributions, please refer to the project repository or contact support.
Version: 0.1.0
Last Updated: January 2026