0
# Storage & Persistence
1
2
localStorage and sessionStorage integration with serialization, synchronization across tabs, and SSR support for persistent application state.
3
4
## Capabilities
5
6
### useLocalStorage
7
8
localStorage integration with serialization, synchronization, and SSR support.
9
10
```typescript { .api }
11
/**
12
* localStorage integration with type safety and serialization
13
* @param props - Configuration object
14
* @returns Tuple of current value, setter, and remover
15
*/
16
function useLocalStorage<T = string>(props: UseStorageOptions<T>): UseStorageReturnValue<T>;
17
18
/**
19
* Read localStorage value without creating a hook
20
* @param props - Configuration object
21
* @returns Current value from localStorage
22
*/
23
function readLocalStorageValue<T>(props: UseStorageOptions<T>): T;
24
25
interface UseStorageOptions<T> {
26
key: string;
27
defaultValue?: T;
28
getInitialValueInEffect?: boolean;
29
sync?: boolean;
30
serialize?: (value: T) => string;
31
deserialize?: (value: string | undefined) => T;
32
}
33
34
type UseStorageReturnValue<T> = [
35
T, // current value
36
(val: T | ((prevState: T) => T)) => void, // setter
37
() => void // remover
38
];
39
```
40
41
**Usage Examples:**
42
43
```typescript
44
import { useLocalStorage } from "@mantine/hooks";
45
46
// String storage
47
const [name, setName, removeName] = useLocalStorage({
48
key: 'user-name',
49
defaultValue: 'Anonymous'
50
});
51
52
// Object storage with custom serialization
53
const [settings, setSettings] = useLocalStorage({
54
key: 'app-settings',
55
defaultValue: { theme: 'light', lang: 'en' },
56
serialize: JSON.stringify,
57
deserialize: (str) => str ? JSON.parse(str) : { theme: 'light', lang: 'en' }
58
});
59
60
// Cross-tab synchronization
61
const [count, setCount] = useLocalStorage({
62
key: 'shared-count',
63
defaultValue: 0,
64
sync: true // Syncs across tabs
65
});
66
67
// SSR-safe initialization
68
const [token, setToken] = useLocalStorage({
69
key: 'auth-token',
70
defaultValue: '',
71
getInitialValueInEffect: true // Prevents hydration mismatch
72
});
73
74
// Usage
75
setName('John Doe');
76
setSettings(prev => ({ ...prev, theme: 'dark' }));
77
removeName(); // Removes from localStorage and resets to default
78
```
79
80
### useSessionStorage
81
82
sessionStorage integration with the same features as useLocalStorage but for session-only persistence.
83
84
```typescript { .api }
85
/**
86
* sessionStorage integration with type safety and serialization
87
* @param props - Configuration object
88
* @returns Tuple of current value, setter, and remover
89
*/
90
function useSessionStorage<T = string>(props: UseStorageOptions<T>): UseStorageReturnValue<T>;
91
92
/**
93
* Read sessionStorage value without creating a hook
94
* @param props - Configuration object
95
* @returns Current value from sessionStorage
96
*/
97
function readSessionStorageValue<T>(props: UseStorageOptions<T>): T;
98
```
99
100
**Usage Examples:**
101
102
```typescript
103
import { useSessionStorage } from "@mantine/hooks";
104
105
// Form data that persists only during session
106
const [formData, setFormData, clearForm] = useSessionStorage({
107
key: 'form-draft',
108
defaultValue: {
109
title: '',
110
content: '',
111
tags: []
112
}
113
});
114
115
// Temporary UI state
116
const [sidebarCollapsed, setSidebarCollapsed] = useSessionStorage({
117
key: 'sidebar-state',
118
defaultValue: false
119
});
120
121
// Shopping cart for session
122
const [cart, setCart] = useSessionStorage({
123
key: 'session-cart',
124
defaultValue: [],
125
sync: true // Sync across tabs in same session
126
});
127
128
// Usage
129
setFormData(prev => ({ ...prev, title: 'New Article' }));
130
setSidebarCollapsed(true);
131
clearForm(); // Clears sessionStorage and resets to default
132
```
133
134
## Storage Patterns
135
136
### Form State Persistence
137
138
```typescript
139
import { useLocalStorage, useSessionStorage } from "@mantine/hooks";
140
141
function ContactForm() {
142
// Persist draft across browser sessions
143
const [draft, setDraft] = useLocalStorage({
144
key: 'contact-form-draft',
145
defaultValue: { name: '', email: '', message: '' }
146
});
147
148
// Temporary form state for current session
149
const [errors, setErrors] = useSessionStorage({
150
key: 'contact-form-errors',
151
defaultValue: {}
152
});
153
154
const handleSubmit = () => {
155
// Clear draft after successful submission
156
setDraft({ name: '', email: '', message: '' });
157
setErrors({});
158
};
159
160
return (
161
<form onSubmit={handleSubmit}>
162
<input
163
value={draft.name}
164
onChange={(e) => setDraft(prev => ({ ...prev, name: e.target.value }))}
165
/>
166
{/* More form fields */}
167
</form>
168
);
169
}
170
```
171
172
### User Preferences
173
174
```typescript
175
import { useLocalStorage } from "@mantine/hooks";
176
177
function useUserPreferences() {
178
const [preferences, setPreferences] = useLocalStorage({
179
key: 'user-preferences',
180
defaultValue: {
181
theme: 'light',
182
language: 'en',
183
notifications: true,
184
autoSave: true
185
},
186
sync: true // Sync across all open tabs
187
});
188
189
const updatePreference = (key: keyof typeof preferences, value: any) => {
190
setPreferences(prev => ({ ...prev, [key]: value }));
191
};
192
193
return { preferences, updatePreference, setPreferences };
194
}
195
```
196
197
### Authentication State
198
199
```typescript
200
import { useLocalStorage } from "@mantine/hooks";
201
202
function useAuth() {
203
const [token, setToken, removeToken] = useLocalStorage({
204
key: 'auth-token',
205
defaultValue: '',
206
getInitialValueInEffect: true // Prevent SSR hydration issues
207
});
208
209
const [user, setUser] = useLocalStorage({
210
key: 'user-data',
211
defaultValue: null,
212
serialize: JSON.stringify,
213
deserialize: (str) => str ? JSON.parse(str) : null
214
});
215
216
const login = (newToken: string, userData: any) => {
217
setToken(newToken);
218
setUser(userData);
219
};
220
221
const logout = () => {
222
removeToken();
223
setUser(null);
224
};
225
226
return { token, user, login, logout, isAuthenticated: !!token };
227
}
228
```
229
230
## Storage Configuration Options
231
232
### Serialization
233
234
Both hooks support custom serialization for complex data types:
235
236
```typescript
237
// Date serialization
238
const [lastVisit, setLastVisit] = useLocalStorage({
239
key: 'last-visit',
240
defaultValue: new Date(),
241
serialize: (date) => date.toISOString(),
242
deserialize: (str) => str ? new Date(str) : new Date()
243
});
244
245
// Complex object with methods
246
const [calculator, setCalculator] = useLocalStorage({
247
key: 'calculator-state',
248
defaultValue: { value: 0, history: [] },
249
serialize: JSON.stringify,
250
deserialize: (str) => {
251
if (!str) return { value: 0, history: [] };
252
const parsed = JSON.parse(str);
253
return {
254
...parsed,
255
// Restore methods if needed
256
calculate: () => { /* logic */ }
257
};
258
}
259
});
260
```
261
262
### SSR Considerations
263
264
```typescript
265
// Prevent hydration mismatches in Next.js/other SSR frameworks
266
const [clientOnlyState, setClientOnlyState] = useLocalStorage({
267
key: 'client-state',
268
defaultValue: null,
269
getInitialValueInEffect: true // Only read from storage after hydration
270
});
271
272
// Use with conditional rendering
273
{clientOnlyState && <ClientOnlyComponent state={clientOnlyState} />}
274
```