Hooks
No hooks found in any category.
useStorage
browserInstallation
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
Property | Type | Description |
---|---|---|
estimate | StorageEstimate | null | Current storage quota and usage information |
isLoading | boolean | True when fetching storage information |
error | string | null | Error message if storage operations fail |
isPersistent | boolean | null | Whether storage is persistent (won't be cleared under pressure) |
usagePercentage | number | null | Percentage of storage quota currently used |
isSupported | boolean | Whether 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