NGXS를 사용한 Angular의 상태 관리 - 2부

NGXS를 사용하여 Angular 애플리케이션의 상태를 관리하는 것이 얼마나 쉬운지 확인하고 Auth0의 SDK와 함께 NGXS를 사용하여 사용자 관련 기능을 처리하는 방법을 알아보세요.






핵심요약: Angular with NGXS 시리즈의 상태 관리의 첫 번째 부분에서 우리는 NGXS의 기본, 작동 방식 및 이를 사용하여 애플리케이션의 상태를 관리하는 방법에 대해 배웠습니다. 2부에서는 NGXS와 함께 Auth0을 사용하여 사용 관련 상태를 관리하는 방법을 보여드리겠습니다.


사용자 상태 관리



사용자 저장소는 메뉴 상태 관리가 작동하는 방식과 유사하게 작동합니다. 상태의 각 부분이 어떻게 작동하는지 자세히 설명하지 않고 Auth0 및 NGXS 통합에 더 중점을 둘 것입니다.

스타터 앱은 Auth0 SDK를 직접 사용하고 RolesService를 통해 역할을 관리합니다. 이 자습서 섹션에서는 NGXS를 통해 Auth0의 SDK를 사용하도록 마이그레이션하고 NGXSSelect 기능을 사용하여 역할을 관리하는 과정을 안내합니다.

사용자 모델 만들기



사용자 상태 개체에 대한 인터페이스 정의부터 시작하겠습니다. user.model.ts를 열고 다음 코드를 추가하세요 👇

// src/app/core/state/user/user.model.ts

import { User as Auth0User } from "@auth0/auth0-spa-js";

export interface UserStateModel {
  userDetails: Auth0User | undefined;
}


다음 코드를 사용하여 user 디렉토리에 대한 배럴 내보내기를 생성합니다 👇

// src/app/core/state/user/index.ts

export * from "./user.model";


가져오기를 더 단순화하려면 state 폴더의 배럴 내보내기에 사용자 폴더를 추가하고 다음 코드를 추가합니다 👇

// src/app/core/state/index.ts

export * from "./menus";

// ✨ New 👇
export * from "./user";


사용자 작업 만들기



사용자 스토어에 필요한 세 가지 사용자 관련 작업이 있습니다. 로그인, 로그아웃 및 사용자 변경 우리 스토어의 사용자 세부 정보를 Auth0의 SDK와 동기화 상태로 유지하기 위한 작업입니다.

Navbar 구성 요소에서 발생하는 여러 사용자 작업이 있으므로 이를 AllNavbarAction로 그룹화하여 애플리케이션의 다른 부분에서 이러한 작업을 재사용하지 않도록 할 수 있습니다(Good Action Hygiene 패턴에 따름).
UserChangedFromAuth0SDK Action은 Auth0의 SDK에서 시작되었으므로 Action 유형의 소스 부분 이름을 Auth0 SDK로 지정하겠습니다.
user.actions.ts를 열고 다음 코드를 추가하세요 👇

// src/app/core/state/user/user.actions.ts

import { User as Auth0User } from "@auth0/auth0-spa-js";

export namespace User {
  export namespace AllNavbarActions {
    export class LoginFlowInitiated {
      static readonly type = "[Navbar] Login Flow Initiated";
    }

    export class LogoutFlowInitiated {
      static readonly type = "[Navbar] Logout Flow Initiated";
    }
  }
  export class UserChangedFromAuth0SDK {
    static readonly type = "[Auth0 SDK] User Changed";
    constructor(public payload: { user: Auth0User | undefined }) {}
  }
}


배럴 내보내기에 user.actions를 추가합니다. index.ts를 열고 다음 코드를 추가하세요 👇

// src/app/core/state/user/index.ts

export * from "./user.model";

// ✨ New 👇
export * from "./user.actions";


사용자 작업을 사용하도록 애플리케이션 업데이트



기사의 첫 번째 부분에서 메뉴 관련 기능을 수행한 것처럼 NGXS의 Actions를 사용하도록 애플리케이션의 사용자 관련 기능을 업데이트해 보겠습니다. 이전 섹션에서 정의한 Action 이름으로 Store 클래스를 주입하고 dispatch 함수를 호출하여 Action을 사용할 수 있습니다.
nav-bar.component.ts를 열고 다음 코드를 추가하세요 👇

// src/app/shared/components/nav-bar/nav-bar.component.ts

import { Component } from "@angular/core";
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { faHome, faUser, faUtensils } from "@fortawesome/free-solid-svg-icons";
import { AuthService } from "@auth0/auth0-angular";

// ✨ New 👇
import { Store } from "@ngxs/store";
import { User } from "src/app/core";

export interface INavBarMenuLinkProps {
  to: string;
  icon: IconDefinition;
  label: string;
}

@Component({
  selector: "app-nav-bar",
  templateUrl: "./nav-bar.component.html",
  styleUrls: ["./nav-bar.component.scss"],
})
export class NavBarComponent {
  faUser = faUser;
  isAuthenticated$ = this.authService.isAuthenticated$;
  user$ = this.authService.user$;

  navOptions: INavBarMenuLinkProps[] = [
    { to: "/home", label: "Home", icon: faHome },
    { to: "/menu", label: "Menu", icon: faUtensils },
  ];

  constructor(
    private authService: AuthService,
    // ✨ New 👇
    private store: Store
  ) {}

  loginWithRedirect(): void {
    // ✨ New 👇
    this.store.dispatch(new User.AllNavbarActions.LoginFlowInitiated());
  }

  logout(): void {
    // ✨ New 👇
    this.store.dispatch(new User.AllNavbarActions.LogoutFlowInitiated());
  }
}


사용자 상태 만들기



사용자 상태 조각에 대한 개별 선택기를 만들기 전에 이 기능을 사용하는 데 필요한 상용구를 만드는 것부터 시작하겠습니다. NGXS는 추가 Injectable 데코레이터와 함께 State 클래스를 사용합니다. user.state.ts를 생성하고 다음 코드를 추가합니다 👇

// src/app/core/state/user/user.state.ts

import { Injectable } from "@angular/core";
import { State } from "@ngxs/store";
import { UserStateModel } from "./user.model";

@State<UserStateModel>({
  name: "user",
  defaults: {
    userDetails: undefined,
  },
})
@Injectable()
export class UserState {}


다음으로 구성 요소가 이러한 속성에 쉽게 액세스할 수 있도록 user , isLoggedIn , userRolesisAdmin 에 대한 일부 유틸리티 선택기를 추가해 보겠습니다. user.state.ts를 열고 다음 코드로 업데이트합니다 👇

// src/app/core/state/user/user.state.ts

import { Injectable } from "@angular/core";
import { UserStateModel } from "./user.model";

// ✨ New 👇
import { State, Selector } from "@ngxs/store";

// ✨ New 👇
import { environment } from "src/environments/environment";

// ✨ New 👇
import { USER_ROLES } from "../../services";

@State<UserStateModel>({
  name: "user",
  defaults: {
    userDetails: undefined,
  },
})
@Injectable()
export class UserState {
  // ✨ New 👇
  @Selector()
  static user(state: UserStateModel) {
    return state.userDetails;
  }

  // ✨ New 👇
  @Selector()
  static isLoggedIn(state: UserStateModel) {
    return !!state.userDetails;
  }

  // ✨ New 👇
  @Selector()
  static userRoles(state: UserStateModel) {
    return (
      state.userDetails?.[`${environment.auth.audience}/roles`] || undefined
    );
  }

  // ✨ New 👇
  @Selector()
  static isAdmin(state: UserStateModel) {
    return state.userDetails?.[`${environment.auth.audience}/roles`]?.includes(
      USER_ROLES.MENU_ADMIN
    );
  }
}

user.state 👇의 내보내기 목록에 index.ts 추가

// src/app/core/state/user/index.ts

export * from "./user.model";
export * from "./user.actions";

// ✨ New 👇
export * from "./user.state";


Read more...

좋은 웹페이지 즐겨찾기