MCPcopy
hub / github.com/coder/mux / usePersistedState

Function usePersistedState

src/browser/hooks/usePersistedState.ts:225–329  ·  view source on GitHub ↗
(
  key: string,
  initialValue: T,
  options?: UsePersistedStateOptions
)

Source from the content-addressed store, hash-verified

223 * @returns [state, setState] tuple matching useState API
224 */
225export function usePersistedState<T>(
226 key: string,
227 initialValue: T,
228 options?: UsePersistedStateOptions
229): [T, Dispatch<SetStateAction<T>>] {
230 // Unique component ID for distinguishing self-updates.
231 const componentIdRef = useRef(Math.random().toString(36));
232
233 ensureStorageListenerInstalled();
234
235 const subscribe = useCallback(
236 (callback: () => void) => {
237 return addSubscriber(key, {
238 callback,
239 componentId: componentIdRef.current,
240 listener: Boolean(options?.listener),
241 });
242 },
243 [key, options?.listener]
244 );
245
246 // Match the previous `usePersistedState` behavior: `initialValue` is only used
247 // as the default when no value is stored; changes to `initialValue` should not
248 // reinitialize state.
249 const initialValueRef = useRef(initialValue);
250
251 // useSyncExternalStore requires getSnapshot() to be referentially stable when
252 // the underlying store value is unchanged. Since localStorage values are JSON,
253 // we cache the parsed value by raw string.
254 const snapshotRef = useRef<{ key: string; raw: string | null; value: T } | null>(null);
255
256 const getSnapshot = useCallback((): T => {
257 if (typeof window === "undefined" || !window.localStorage) {
258 return initialValueRef.current;
259 }
260
261 try {
262 const raw = window.localStorage.getItem(key);
263
264 if (raw === null || raw === "undefined") {
265 if (snapshotRef.current?.key === key && snapshotRef.current.raw === null) {
266 return snapshotRef.current.value;
267 }
268
269 snapshotRef.current = {
270 key,
271 raw: null,
272 value: initialValueRef.current,
273 };
274
275 return initialValueRef.current;
276 }
277
278 if (snapshotRef.current?.key === key && snapshotRef.current.raw === raw) {
279 return snapshotRef.current.value;
280 }
281
282 const parsed = JSON.parse(raw) as T;

Callers 15

AppInnerFunction · 0.90
VimTextArea.tsxFile · 0.90
ProjectSidebarInnerFunction · 0.90
RosettaBannerFunction · 0.90
WorkspaceShellFunction · 0.90
ArchivedWorkspacesFunction · 0.90
ProjectPageFunction · 0.90
WorkspaceModeAISyncFunction · 0.90
TerminalViewFunction · 0.90
ChatPaneContentFunction · 0.90
GitStatusIndicatorFunction · 0.90

Calls 11

getStorageChangeEventFunction · 0.90
addSubscriberFunction · 0.85
readPersistedStateFunction · 0.85
notifyWriteListenersFunction · 0.85
notifySubscribersFunction · 0.85
dispatchEventMethod · 0.80
getItemMethod · 0.65
parseMethod · 0.45
removeItemMethod · 0.45
setItemMethod · 0.45

Tested by

no test coverage detected