ngrx-store-localstorage with angular 17 standalone component

73 Views Asked by At

I'm using ngrx-store-localstorage to persist my store in localstorage in an angular 17 project, using the new standalone method.

this is how i configure my meta reducer:

export function localStorageSyncConfig(): LocalStorageConfig {
  return {
    keys: ['identity'], // Replace with your actual state key
    rehydrate: true,
  };
}
export function localStorageSyncReducer(reducer: any): any {
  return localStorageSync(localStorageSyncConfig())(reducer);
}

and this is my app.config.ts:

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideClientHydration(),
    provideStore(localStorageSyncReducer(IdentityReducer)),
    provideEffects([IdentityEffect]),
    provideStoreDevtools({
      maxAge: 25,
      logOnly: !isDevMode(),
      autoPause: true,
      trace: false,
      traceLimit: 75,
    }),
  ],
};

and when i build the project i get this error: enter image description here

what i'm i missing??

2

There are 2 best solutions below

4
Naren Murali On

Try adding checkStorageAvailability in the local storage config

I think for SSR you are getting this error, since window does not exist on the server!

Github issue

PR changes

export function localStorageSyncConfig(): LocalStorageConfig {
  return {
    keys: ['identity'], // Replace with your actual state key
    rehydrate: true,
    checkStorageAvailability: true, //<- changed here!
  };
}
export function localStorageSyncReducer(reducer: any): any {
  return localStorageSync(localStorageSyncConfig())(reducer);
}
0
Eni Guma On

Yes, the issue was resolved after using checkStorageAvailability. When I trigger a state update, the state is successfully synchronized to localStorage. However, the state is not being retrieved from localStorage when the page reloads. The stored state remains empty after initialization.

I hope that when the store triggers an action, the state can be updated and synchronized to localStorage. When the page is refreshed, I expect the store initialization to synchronize back from localStorage.

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideClientHydration(withHttpTransferCacheOptions({
      includePostRequests: true
    })),
    provideAnimationsAsync(),
    provideHttpClient(withFetch(), withInterceptors([authInterceptor])),
    provideStore(localStorageSyncReducer(loginReducer)),
    provideEffects(LoginEffects),
    provideState({ name: 'login', reducer: loginReducer }),
    {
      provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
      useValue: {
        subscriptSizing: 'dynamic'
      }
    }
  ]
};

export interface State {
  accessToken: string;
  error: string;
  isLoading: boolean;
  isLoggin: boolean;
}

const initialState: State = {
  accessToken: '',
  error: '',
  isLoading: false,
  isLoggin: false
};

export const loginReducer = createReducer(initialState,
  on(login, state => ({ ...state, isLoading: true })),
  on(loginSuccess, (state, { accessToken }) => ({ ...state, accessToken: accessToken, isLoading: false, isLoggin: true })),
  on(loginFailure, (state, { error }) => ({ ...state, error, isLoading: false, isLoggin: false })),
  on(logout, () => initialState)
);

export function localStorageSyncConfig(): LocalStorageConfig {
  return {
    keys: ['accessToken'],
    rehydrate: true,
    checkStorageAvailability: true,
  };
}
export function localStorageSyncReducer(reducer: any): any {
  return localStorageSync(localStorageSyncConfig())(reducer);
}