NgRx provides a powerful, Redux-inspired way to manage state in Angular applications. By following proven patterns and best practices, you keep your store maintainable, testable, and scalable as your app grows.
OnPush change detection to minimize re-renders.feature/state/ for actions, reducers, selectors, and effects.index.ts files to export all feature-related items for cleaner imports.[Feature] Action Description (e.g., [Auth] Login Success).selectFeatureNameProperty (e.g., selectAuthUser).featureReducer (e.g., authReducer).Selectors provide a reusable, memoized way to read data from the store. They keep components simple and prevent duplicated state-selection logic across the app.
// auth.selectors.ts - strongly typed selectors for the auth feature
import { createFeatureSelector, createSelector } from '@ngrx/store';
import { AuthState } from './auth.reducer';
export const selectAuthState = createFeatureSelector<AuthState>('auth');
export const selectUser = createSelector(
selectAuthState,
(state: AuthState) => state.user
);
catchError in effects.{ dispatch: false } when an effect does not dispatch an action.exhaustMap, switchMap, or concatMap appropriately for your use case.
// auth.effects.ts - handle login request and success/error actions
@Injectable()
export class AuthEffects {
login$ = createEffect(() =>
this.actions$.pipe(
ofType(AuthActions.login),
exhaustMap(action =>
this.authService.login(action.credentials).pipe(
map(user => AuthActions.loginSuccess({ user })),
catchError(error => of(AuthActions.loginFailure({ error })))
)
)
)
);
constructor(
private actions$: Actions,
private authService: AuthService
) {}
}
In the selectors example, selectAuthState reads the auth slice from the global store, and selectUser derives the user from that slice. Components subscribe to selectUser to reactively display the current user.
AuthActions.login and perform async work.loginSuccess, which reducers use to update the store.loginFailure, so the UI can show an error state.OnPush change detection in components to optimize performance with the store.feature/state/ folder structure.OnPush change detection on your smart and dumb components and observe performance improvements.