@@ -564,6 +564,72 @@ export function useList(defaultList = []) {
564
564
return [ list , { set, push, removeAt, insertAt, updateAt, clear } ] ;
565
565
}
566
566
567
+ const dispatchStorageEvent = ( key , newValue ) => {
568
+ window . dispatchEvent ( new StorageEvent ( "storage" , { key, newValue } ) ) ;
569
+ } ;
570
+
571
+ const setLocalStorageItem = ( key , value ) => {
572
+ const stringifiedValue = JSON . stringify ( value ) ;
573
+ window . localStorage . setItem ( key , stringifiedValue ) ;
574
+ dispatchStorageEvent ( key , stringifiedValue ) ;
575
+ } ;
576
+
577
+ const removeLocalStorageItem = ( key ) => {
578
+ window . localStorage . removeItem ( key ) ;
579
+ dispatchStorageEvent ( key , null ) ;
580
+ } ;
581
+
582
+ const getLocalStorageItem = ( key ) => {
583
+ return window . localStorage . getItem ( key ) ;
584
+ } ;
585
+
586
+ const useLocalStorageSubscribe = ( callback ) => {
587
+ window . addEventListener ( "storage" , callback ) ;
588
+ return ( ) => window . removeEventListener ( "storage" , callback ) ;
589
+ } ;
590
+
591
+ const getLocalStorageServerSnapshot = ( ) => {
592
+ throw Error ( "useLocalStorage is a client-only hook" ) ;
593
+ } ;
594
+
595
+ export function useLocalStorage ( key , initialValue ) {
596
+ const getSnapshot = ( ) => getLocalStorageItem ( key ) ;
597
+
598
+ const store = React . useSyncExternalStore (
599
+ useLocalStorageSubscribe ,
600
+ getSnapshot ,
601
+ getLocalStorageServerSnapshot
602
+ ) ;
603
+
604
+ const setState = React . useCallback (
605
+ ( v ) => {
606
+ try {
607
+ const nextState = typeof v === "function" ? v ( JSON . parse ( store ) ) : v ;
608
+
609
+ if ( nextState === undefined || nextState === null ) {
610
+ removeLocalStorageItem ( key ) ;
611
+ } else {
612
+ setLocalStorageItem ( key , nextState ) ;
613
+ }
614
+ } catch ( e ) {
615
+ console . warn ( e ) ;
616
+ }
617
+ } ,
618
+ [ key , store ]
619
+ ) ;
620
+
621
+ React . useEffect ( ( ) => {
622
+ if (
623
+ getLocalStorageItem ( key ) === null &&
624
+ typeof initialValue !== "undefined"
625
+ ) {
626
+ setLocalStorageItem ( key , initialValue ) ;
627
+ }
628
+ } , [ key , initialValue ] ) ;
629
+
630
+ return [ store ? JSON . parse ( store ) : initialValue , setState ] ;
631
+ }
632
+
567
633
export function useLockBodyScroll ( ) {
568
634
React . useEffect ( ( ) => {
569
635
const originalStyle = window . getComputedStyle ( document . body ) . overflow ;
0 commit comments