]> juplo.de Git - demos/angular/stored-login/commitdiff
feature: persist `username` to and rehydrate it from local-storage
authorKai Moritz <kai@juplo.de>
Mon, 15 Sep 2025 21:45:44 +0000 (23:45 +0200)
committerKai Moritz <kai@juplo.de>
Tue, 16 Sep 2025 19:26:15 +0000 (21:26 +0200)
src/app/app.config.ts
src/app/store/login.metareducer.ts [new file with mode: 0644]

index 115142edd361b186f01e1bdc2db28c37f6688451..288833e5f6e8e5e448128e77e6ee34db2c44e1a8 100644 (file)
@@ -6,10 +6,11 @@ import { provideStore } from '@ngrx/store';
 import { provideEffects } from '@ngrx/effects';
 import { loginReducers } from './store/login.reducers';
 import { LoginEffects } from './store/login.effects';
+import { loginMetaReducer } from './store/login.metareducer';
 
 export const appConfig: ApplicationConfig = {
   providers: [
-    provideStore({ login : loginReducers }),
+    provideStore({ login : loginReducers }, { metaReducers: [loginMetaReducer] }),
     provideEffects([LoginEffects]),
     provideZoneChangeDetection({ eventCoalescing: true }),
     provideRouter(routes)
diff --git a/src/app/store/login.metareducer.ts b/src/app/store/login.metareducer.ts
new file mode 100644 (file)
index 0000000..5a03f6e
--- /dev/null
@@ -0,0 +1,44 @@
+import { Action, ActionReducer, INIT, UPDATE } from '@ngrx/store';
+import { State } from './login.reducers';
+
+const STORAGE_KEY = 'login';
+
+function saveStateSlice(state: State) {
+  const { username } = state;
+  return { username };
+}
+
+export function loginMetaReducer<S, A extends Action<string>>(reducer: ActionReducer<S, A>): ActionReducer<S, A> {
+  return (state, action) => {
+    // 1) Rehydrate beim App-Start
+    if (action.type === INIT || action.type === UPDATE) {
+      const storedState = localStorage.getItem(STORAGE_KEY);
+      if (storedState) {
+        try {
+          const parsed = JSON.parse(storedState) as Partial<State>;
+          // vorhandenen State um gespeicherte Felder erweitern
+          return {
+            ...state,
+            login: {
+              ...(state as any)?.login,
+              ...parsed
+            }
+          };
+        } catch {
+          localStorage.removeItem(STORAGE_KEY);
+        }
+      }
+    }
+
+    // 2) Normal Reducer ausführen
+    const nextState : any = reducer(state, action);
+
+    // 3) Nur login-Slice persistieren
+    const loginSlice = (nextState as any)?.login as State;
+    if (loginSlice) {
+      localStorage.setItem(STORAGE_KEY, JSON.stringify(saveStateSlice(loginSlice)));
+    }
+
+    return nextState;
+  };
+}