React hook integration for declarative permission management with automatic status fetching, lifecycle handling, and memoized callbacks.
React hook for managing permissions declaratively with automatic fetching on mount and lifecycle-aware state management.
/**
* Get or ask permission for protected functionality within the app.
* Returns the permission response after fetching or asking it.
* The hook fetches the permissions when rendered, by default.
* To ask the user permission, use the askPermission callback or ask option.
*
* @param type - Single permission type or array of permission types
* @param options - Optional configuration object
* @returns Tuple of [permission, askPermission, getPermission]
* @deprecated Package deprecated - use individual Expo modules instead
*/
function usePermissions(
type: PermissionType | PermissionType[],
options?: PermissionsOptions
): [PermissionResponse | undefined, () => Promise<void>, () => Promise<void>];
interface PermissionsOptions {
/** If it should ask the permissions when mounted, defaults to false */
ask?: boolean;
/** If it should fetch information about the permissions when mounted, defaults to true */
get?: boolean;
}Usage Examples:
import React from 'react';
import { usePermissions, CAMERA, MEDIA_LIBRARY, LOCATION_FOREGROUND, NOTIFICATIONS } from 'expo-permissions';
import { Camera } from 'expo-camera';
import { Button, Text, View } from 'react-native';
// Basic usage with single permission
function CameraScreen() {
const [permission, askPermission, getPermission] = usePermissions(CAMERA);
if (!permission) {
return <Text>Loading permission status...</Text>;
}
if (!permission.granted) {
return (
<View>
<Text>Camera permission not granted</Text>
<Button title="Grant Camera Permission" onPress={askPermission} />
</View>
);
}
return <Camera style={{ flex: 1 }} />;
}
// Multiple permissions
function MediaScreen() {
const [permissions, askPermissions] = usePermissions([CAMERA, MEDIA_LIBRARY]);
return (
<View>
{permissions?.granted ? (
<Text>All permissions granted!</Text>
) : (
<Button title="Request Permissions" onPress={askPermissions} />
)}
</View>
);
}
// Auto-ask on mount
function AutoRequestScreen() {
const [permission] = usePermissions(LOCATION_FOREGROUND, { ask: true });
return (
<View>
<Text>Status: {permission?.status || 'Loading...'}</Text>
</View>
);
}
// Manual control (no auto-fetch)
function ManualScreen() {
const [permission, askPermission, getPermission] = usePermissions(
NOTIFICATIONS,
{ get: false }
);
return (
<View>
<Button title="Check Permission" onPress={getPermission} />
<Button title="Request Permission" onPress={askPermission} />
{permission && <Text>Status: {permission.status}</Text>}
</View>
);
}getAsync on mount when get: true (default)get: false to prevent automatic permission checkingask: true to automatically request permissions on mountaskPermission and getPermission callbacks are memoized based on permission typesundefined until first fetch completesThe hook returns a tuple with three elements:
type UsePermissionsReturn = [
PermissionResponse | undefined, // Current permission state
() => Promise<void>, // Ask permission function
() => Promise<void> // Get permission function
];undefined: Initial state before any permission fetchPermissionResponse: Complete permission information including status, expiration, and individual permission detailsaskAsync with the specified permission typesgetAsync with the specified permission typesfunction ConditionalFeature() {
const [permission, askPermission] = usePermissions(CAMERA);
// Handle loading state
if (!permission) {
return <LoadingSpinner />;
}
// Handle different permission states
switch (permission.status) {
case 'granted':
return <CameraFeature />;
case 'denied':
return (
<View>
<Text>Camera access denied</Text>
{permission.canAskAgain && (
<Button title="Try Again" onPress={askPermission} />
)}
</View>
);
case 'undetermined':
return (
<View>
<Text>Camera permission needed</Text>
<Button title="Grant Permission" onPress={askPermission} />
</View>
);
}
}function MultiPermissionFeature() {
const [permissions, askPermissions] = usePermissions([
CAMERA,
MEDIA_LIBRARY,
LOCATION_FOREGROUND
]);
if (!permissions) return <Text>Loading...</Text>;
// Check individual permissions
const cameraGranted = permissions.permissions.camera?.granted;
const mediaGranted = permissions.permissions.mediaLibrary?.granted;
const locationGranted = permissions.permissions.locationForeground?.granted;
return (
<View>
<Text>Camera: {cameraGranted ? '✓' : '✗'}</Text>
<Text>Media: {mediaGranted ? '✓' : '✗'}</Text>
<Text>Location: {locationGranted ? '✓' : '✗'}</Text>
{!permissions.granted && (
<Button title="Request All" onPress={askPermissions} />
)}
</View>
);
}function EffectIntegration() {
const [permission, askPermission] = usePermissions(LOCATION_FOREGROUND);
// React to permission changes
useEffect(() => {
if (permission?.granted) {
// Start location tracking
startLocationUpdates();
} else {
// Stop location tracking
stopLocationUpdates();
}
}, [permission?.granted]);
return (
<View>
{permission?.granted ? (
<LocationMap />
) : (
<Button title="Enable Location" onPress={askPermission} />
)}
</View>
);
}