UNPKG

@supunlakmal/hooks

Version:

A collection of reusable React hooks

64 lines 3.04 kB
import { useState, useEffect, useCallback } from 'react'; /** * Custom hook to query the status of a browser permission using the Permissions API. * * @param {PermissionDescriptor} permissionDesc - An object describing the permission to query (e.g., { name: 'geolocation' }). * @returns {UsePermissionState} An object containing the permission state, support status, and a function to re-query. */ export const usePermission = (permissionDesc) => { const [state, setState] = useState('querying'); const [isSupported, setIsSupported] = useState(false); const [permissionStatus, setPermissionStatus] = useState(null); const queryPermission = useCallback(async () => { if (typeof navigator === 'undefined' || !navigator.permissions) { setIsSupported(false); setState('unsupported'); setPermissionStatus(null); return; } setIsSupported(true); setState('querying'); // Set state to querying before async call setPermissionStatus(null); try { const status = await navigator.permissions.query(permissionDesc); setPermissionStatus(status); setState(status.state); // Set up the change listener status.onchange = () => { setState(status.state); }; } catch (error) { console.error(`Error querying permission '${permissionDesc.name}':`, error); // If query fails (e.g., unrecognized permission), treat as unsupported or denied? // Let's default to 'denied' or maybe a specific 'error' state? // For simplicity, sticking to 'denied' if query fails after support check. setState('denied'); setPermissionStatus(null); } }, [permissionDesc]); // Re-query if permissionDesc changes useEffect(() => { queryPermission(); // Cleanup function to remove the listener if the permissionStatus object exists // This is important if the component unmounts before the query completes or if permissionDesc changes const currentStatus = permissionStatus; // Capture status at the time effect runs return () => { if (currentStatus) { currentStatus.onchange = null; } }; }, [queryPermission]); // Run effect when queryPermission function updates // Need to add manual cleanup for the listener on the *previous* status object // when the permissionDesc changes and a new query is initiated. useEffect(() => { // Store the previous status object to remove its listener on change const previousStatus = permissionStatus; return () => { if (previousStatus) { previousStatus.onchange = null; } }; }, [permissionStatus]); // Run cleanup when permissionStatus object itself changes return { state, isSupported, query: queryPermission }; }; //# sourceMappingURL=usePermission.js.map