@@ -564,6 +564,72 @@ export function useList(defaultList = []) {
564564 return [ list , { set, push, removeAt, insertAt, updateAt, clear } ] ;
565565}
566566
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+
567633export function useLockBodyScroll ( ) {
568634 React . useEffect ( ( ) => {
569635 const originalStyle = window . getComputedStyle ( document . body ) . overflow ;
0 commit comments