useHooks.iov4.1.2
DocsBlogGitHub
Hooks
No hooks found in any category.

useStorage

browser

Installation

npx usehooks-cli@latest add use-storage

Description

A React hook for managing browser storage quotas and persistence using the Storage API. Provides storage estimation, usage monitoring, and persistent storage management.

Return Type

UseStorageReturn
PropertyTypeDescription
estimateStorageEstimate | nullCurrent storage quota and usage information
isLoadingbooleanTrue when fetching storage information
errorstring | nullError message if storage operations fail
isPersistentboolean | nullWhether storage is persistent (won't be cleared under pressure)
usagePercentagenumber | nullPercentage of storage quota currently used
isSupportedbooleanWhether the Storage API is supported in this browser
getEstimate() => Promise<StorageEstimate | null>Manually refresh storage estimate
requestPersistentStorage() => Promise<boolean>Request persistent storage permission from the browser
checkPersistence() => Promise<boolean>Check if storage is currently persistent

Examples

Storage Usage Monitor

Displaying current storage usage and quota information

1const { 2 estimate, 3 usagePercentage, 4 isLoading, 5 error, 6 isSupported 7} = useStorage(); 8 9if (!isSupported) { 10 return <div>Storage API not supported</div>; 11} 12 13if (isLoading) { 14 return <div>Loading storage info...</div>; 15} 16 17if (error) { 18 return <div>Error: {error}</div>; 19} 20 21return ( 22 <div className="storage-info"> 23 <h3>Storage Usage</h3> 24 {estimate && ( 25 <> 26 <div className="usage-bar"> 27 <div 28 className="usage-fill" 29 style={{ width: `${usagePercentage}%` }} 30 /> 31 </div> 32 <p> 33 Used: {(estimate.usage / 1024 / 1024).toFixed(2)} MB of{' '} 34 {(estimate.quota / 1024 / 1024).toFixed(2)} MB 35 ({usagePercentage}%) 36 </p> 37 {estimate.usageDetails && ( 38 <div className="usage-details"> 39 <h4>Usage by type:</h4> 40 {Object.entries(estimate.usageDetails).map(([key, value]) => ( 41 <p key={key}> 42 {key}: {(value / 1024 / 1024).toFixed(2)} MB 43 </p> 44 ))} 45 </div> 46 )} 47 </> 48 )} 49 </div> 50);

Persistent Storage Manager

Managing persistent storage permissions and status

1const { 2 isPersistent, 3 requestPersistentStorage, 4 checkPersistence, 5 error 6} = useStorage(); 7const [isRequesting, setIsRequesting] = useState(false); 8 9const handleRequestPersistent = async () => { 10 setIsRequesting(true); 11 try { 12 const granted = await requestPersistentStorage(); 13 if (granted) { 14 showToast('Persistent storage granted!'); 15 } else { 16 showToast('Persistent storage denied'); 17 } 18 } catch (err) { 19 showToast('Failed to request persistent storage'); 20 } finally { 21 setIsRequesting(false); 22 } 23}; 24 25const handleCheckPersistence = async () => { 26 await checkPersistence(); 27}; 28 29return ( 30 <div className="persistence-manager"> 31 <h3>Storage Persistence</h3> 32 33 <div className="status"> 34 Status: { 35 isPersistent === null ? 'Unknown' : 36 isPersistent ? '✅ Persistent' : '⚠️ Not Persistent' 37 } 38 </div> 39 40 {!isPersistent && ( 41 <div className="warning"> 42 <p>Your data may be cleared when storage is low.</p> 43 <button 44 onClick={handleRequestPersistent} 45 disabled={isRequesting} 46 > 47 {isRequesting ? 'Requesting...' : 'Request Persistent Storage'} 48 </button> 49 </div> 50 )} 51 52 <button onClick={handleCheckPersistence}> 53 Refresh Status 54 </button> 55 56 {error && <div className="error">{error}</div>} 57 </div> 58);

Storage Quota Warning

Warning users when storage is running low

1const { 2 estimate, 3 usagePercentage, 4 getEstimate, 5 requestPersistentStorage 6} = useStorage(); 7const [showWarning, setShowWarning] = useState(false); 8 9// Check storage usage periodically 10useEffect(() => { 11 const interval = setInterval(() => { 12 getEstimate(); 13 }, 60000); // Check every minute 14 15 return () => clearInterval(interval); 16}, [getEstimate]); 17 18// Show warning when storage is getting full 19useEffect(() => { 20 if (usagePercentage && usagePercentage > 80) { 21 setShowWarning(true); 22 } else { 23 setShowWarning(false); 24 } 25}, [usagePercentage]); 26 27const handleClearCache = async () => { 28 // Clear application cache 29 await clearApplicationCache(); 30 await getEstimate(); // Refresh storage info 31 showToast('Cache cleared successfully'); 32}; 33 34return ( 35 <div> 36 {showWarning && ( 37 <div className="storage-warning"> 38 <h4>⚠️ Storage Running Low</h4> 39 <p> 40 You're using {usagePercentage}% of your available storage. 41 Consider clearing some data or requesting persistent storage. 42 </p> 43 <div className="warning-actions"> 44 <button onClick={handleClearCache}> 45 Clear Cache 46 </button> 47 <button onClick={requestPersistentStorage}> 48 Request Persistent Storage 49 </button> 50 </div> 51 </div> 52 )} 53 54 {/* Rest of your app */} 55 </div> 56);

Dependencies

react

Notes

  • Requires a modern browser with Storage API support
  • Automatically fetches storage estimate and persistence status on mount
  • Persistent storage prevents data from being cleared under storage pressure
  • Storage estimates are approximate and may vary between browsers
  • Useful for PWAs and applications that store significant amounts of data
  • Provides both automatic monitoring and manual control methods

Implementation

1'use client'; 2 3import { useState, useEffect, useCallback } from "react"; 4 5interface StorageEstimate { 6 quota?: number; 7 usage?: number; 8 usageDetails?: { 9 [key: string]: number; 10 }; 11} 12 13interface UseStorageReturn { 14 // Storage estimation 15 estimate: StorageEstimate | null; 16 isLoading: boolean; 17 error: string | null; 18 19 // Persistence management 20 isPersistent: boolean | null; 21 22 // Methods 23 getEstimate: () => Promise<StorageEstimate | null>; 24 requestPersistentStorage: () => Promise<boolean>; 25 checkPersistence: () => Promise<boolean>; 26 27 // Computed values 28 usagePercentage: number | null; 29 isSupported: boolean; 30} 31 32export const useStorage = (): UseStorageReturn => { 33 const [estimate, setEstimate] = useState<StorageEstimate | null>(null); 34 const [isPersistent, setIsPersistent] = useState<boolean | null>(null); 35 const [isLoading, setIsLoading] = useState(false); 36 const [error, setError] = useState<string | null>(null); 37 38 // Check if Storage API is supported 39 const isSupported = 40 typeof navigator !== "undefined" && 41 "storage" in navigator && 42 typeof navigator.storage.estimate === "function"; 43 44 // Get storage estimate 45 const getEstimate = useCallback(async (): Promise<StorageEstimate | null> => { 46 if (!isSupported) { 47 setError("Storage API is not supported"); 48 return null; 49 } 50 51 try { 52 setIsLoading(true); 53 setError(null); 54 55 const storageEstimate = await navigator.storage.estimate(); 56 setEstimate(storageEstimate); 57 return storageEstimate; 58 } catch (err) { 59 const errorMessage = 60 err instanceof Error ? err.message : "Failed to get storage estimate"; 61 setError(errorMessage); 62 return null; 63 } finally { 64 setIsLoading(false); 65 } 66 }, [isSupported]); 67 68 // Request persistent storage 69 const requestPersistentStorage = useCallback(async (): Promise<boolean> => { 70 if (!isSupported || !navigator.storage.persist) { 71 setError("Persistent storage is not supported"); 72 return false; 73 } 74 75 try { 76 setError(null); 77 const persistent = await navigator.storage.persist(); 78 setIsPersistent(persistent); 79 return persistent; 80 } catch (err) { 81 const errorMessage = 82 err instanceof Error 83 ? err.message 84 : "Failed to request persistent storage"; 85 setError(errorMessage); 86 return false; 87 } 88 }, [isSupported]); 89 90 // Check if storage is persistent 91 const checkPersistence = useCallback(async (): Promise<boolean> => { 92 if (!isSupported || !navigator.storage.persisted) { 93 setError("Persistence check is not supported"); 94 return false; 95 } 96 97 try { 98 setError(null); 99 const persistent = await navigator.storage.persisted(); 100 setIsPersistent(persistent); 101 return persistent; 102 } catch (err) { 103 const errorMessage = 104 err instanceof Error ? err.message : "Failed to check persistence"; 105 setError(errorMessage); 106 return false; 107 } 108 }, [isSupported]); 109 110 // Calculate usage percentage 111 const usagePercentage = 112 estimate?.quota && estimate?.usage 113 ? Math.round((estimate.usage / estimate.quota) * 100) 114 : null; 115 116 // Initialize on mount 117 useEffect(() => { 118 if (isSupported) { 119 getEstimate(); 120 checkPersistence(); 121 } 122 }, [isSupported, getEstimate, checkPersistence]); 123 124 return { 125 estimate, 126 isLoading, 127 error, 128 isPersistent, 129 getEstimate, 130 requestPersistentStorage, 131 checkPersistence, 132 usagePercentage, 133 isSupported, 134 }; 135}; 136