Deprecated centralized permissions API for React Native and Expo applications
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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>
);
}