# NgRx State Management {#ngrx-state-management}


Angular frontend state management with NgRx.


## Overview {#overview}


The Gauzy Angular frontend uses NgRx for centralized state management:

- Predictable state container
- Unidirectional data flow
- Debugging with Redux DevTools
- Side effect management with Effects


## Architecture {#architecture}






```mermaid
graph LR
    Component -->|dispatch| Action
    Action --> Reducer
    Reducer --> Store[(Store)]
    Store -->|select| Component
    Action --> Effect
    Effect -->|API call| Service
    Service --> Effect
    Effect -->|dispatch| Action2[Success/Failure Action]
```






## Example: Task State {#example-task-state}



### Actions {#actions}


```typescript
// task.actions.ts
import { createAction, props } from "@ngrx/store";

export const loadTasks = createAction("[Task] Load Tasks");
export const loadTasksSuccess = createAction(
  "[Task] Load Tasks Success",
  props<{ tasks: ITask[]; total: number }>(),
);
export const loadTasksFailure = createAction(
  "[Task] Load Tasks Failure",
  props<{ error: string }>(),
);
export const createTask = createAction(
  "[Task] Create",
  props<{ task: ICreateTask }>(),
);
```


### Reducer {#reducer}


```typescript
// task.reducer.ts
export interface TaskState {
  tasks: ITask[];
  total: number;
  loading: boolean;
  error: string | null;
}

const initialState: TaskState = {
  tasks: [],
  total: 0,
  loading: false,
  error: null,
};

export const taskReducer = createReducer(
  initialState,
  on(loadTasks, (state) => ({ ...state, loading: true })),
  on(loadTasksSuccess, (state, { tasks, total }) => ({
    ...state,
    tasks,
    total,
    loading: false,
  })),
  on(loadTasksFailure, (state, { error }) => ({
    ...state,
    error,
    loading: false,
  })),
);
```


### Selectors {#selectors}


```typescript
// task.selectors.ts
export const selectTaskState = createFeatureSelector<TaskState>("task");
export const selectAllTasks = createSelector(selectTaskState, (s) => s.tasks);
export const selectTasksLoading = createSelector(
  selectTaskState,
  (s) => s.loading,
);
export const selectTaskCount = createSelector(selectTaskState, (s) => s.total);
```


### Effects {#effects}


```typescript
// task.effects.ts
@Injectable()
export class TaskEffects {
  loadTasks$ = createEffect(() =>
    this.actions$.pipe(
      ofType(loadTasks),
      switchMap(() =>
        this.taskService.getAll().pipe(
          map((result) => loadTasksSuccess(result)),
          catchError((error) => of(loadTasksFailure({ error: error.message }))),
        ),
      ),
    ),
  );

  constructor(
    private actions$: Actions,
    private taskService: TaskService,
  ) {}
}
```


## Related Pages {#related-pages}


- [Angular Module Architecture](https://sourcey-gauzy.pages.dev/frontend/angular-module-architecture/index.md) — modules
- [Form Handling Patterns](https://sourcey-gauzy.pages.dev/frontend/form-handling-patterns/index.md) — forms
