One Calendar is a privacy-first calendar web app built with Next.js. It has modern security features, including e2ee, password-protected sharing, and self-destructing share links ๐Ÿ“… calendar.xyehr.cn
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(storage): prevent restored preferences from being overwritten by stale reads

+12 -2
+12 -2
hooks/useLocalStorage.ts
··· 1 1 "use client" 2 2 3 - import { useEffect, useState } from "react" 3 + import { useEffect, useRef, useState, type SetStateAction } from "react" 4 4 import { decryptPayload, encryptPayload, isEncryptedPayload } from "@/lib/crypto" 5 5 6 6 type EncryptionState = { ··· 320 320 export function useLocalStorage<T>(key: string, initialValue: T) { 321 321 const [storedValue, setStoredValue] = useState<T>(initialValue) 322 322 const [serializedValue, setSerializedValue] = useState(() => JSON.stringify(initialValue)) 323 + const localWriteVersionRef = useRef(0) 324 + 325 + const updateStoredValue = (value: SetStateAction<T>) => { 326 + localWriteVersionRef.current += 1 327 + setStoredValue(value) 328 + } 323 329 324 330 useEffect(() => { 325 331 let cancelled = false 332 + const writeVersionWhenReadStarted = localWriteVersionRef.current 326 333 readLocalStorage(key, initialValue).then((value) => { 327 334 if (cancelled) return 335 + if (localWriteVersionRef.current !== writeVersionWhenReadStarted) return 328 336 const nextSerializedValue = JSON.stringify(value) 329 337 setSerializedValue(nextSerializedValue) 330 338 setStoredValue((prev) => { ··· 341 349 342 350 useEffect(() => { 343 351 const refreshValue = () => { 352 + const writeVersionWhenReadStarted = localWriteVersionRef.current 344 353 readLocalStorage(key, initialValue).then((value) => { 354 + if (localWriteVersionRef.current !== writeVersionWhenReadStarted) return 345 355 const nextSerializedValue = JSON.stringify(value) 346 356 setSerializedValue(nextSerializedValue) 347 357 setStoredValue((prev) => { ··· 384 394 void writeLocalStorage(key, storedValue) 385 395 }, [key, serializedValue, storedValue]) 386 396 387 - return [storedValue, setStoredValue] as const 397 + return [storedValue, updateStoredValue] as const 388 398 }