이 글은 여러분에게 Angular의 상태 관리자 NgRx에 대한 심층적인 이해를 제공하고 NgRx 사용 방법을 소개할 것입니다. 도움이 되길 바랍니다!
NgRx는 Angular 애플리케이션의 전역 상태 관리를 위한 Redux 아키텍처 솔루션입니다. [관련 추천 튜토리얼: "Angular 튜토리얼"]

@ngrx/store: 전역 상태 관리 모듈
@ngrx/효과: 부작용 처리
@ngrx/store-devtools: 브라우저 디버깅 도구, Redux Devtools Extension에 의존해야 함
@ngrx/schematics: NgRx 파일을 빠르게 생성하는 명령줄 도구
@ngrx/entity: 개발자의 Reducer 데이터 운영 효율성 향상
@ngrx/router-store: 라우팅 상태를 글로벌 스토어에 동기화
1. NgRx 다운로드
npm install @ngrx/store @ngrx/effects @ngrx/entity @ngrx/router-store @ngrx/store-devtools @ngrx/schematics
2. NgRx CLI 구성
ng config cli.defaultCollection @ngrx/schematics
// 각도.json
"cli": {
"defaultCollection": "@ngrx/schematics"
}3. 스토어 생성
ng g store State --root --module app.module.ts --statePath store --stateInterface AppState
4. 액션 생성
ng g action store/actions/counter --skipTests
"@ngrx/store"에서 { createAction } 가져오기
const 증분 내보내기 = createAction("증분")
const 감소 = createAction("감소") 내보내기5. 리듀서 생성
ng g reducer store/reducers/counter --skipTests --reducers=../index.ts
"@ngrx/store"에서 가져오기 { createReducer, on }
"../actions/counter.actions"에서 { 감소, 증가 } 가져오기
const counterFeatureKey = "카운터" 내보내기
내보내기 인터페이스 상태 {
개수: 숫자
}
constinitialState 내보내기: 상태 = {
개수: 0
}
const 감속기 내보내기 = createReducer(
초기 상태,
on(증분, 상태 => ({ 개수: state.count + 1 })),
on(감소, 상태 => ({ 개수: state.count - 1 }))
)6. 선택기 생성
ng g selector store/selectors/counter --skipTests
"@ngrx/store"에서 { createFeatureSelector, createSelector } 가져오기
"../reducers/counter.reducer"에서 { counterFeatureKey, State } 가져오기
".."에서 { AppState } 가져오기
내보내기 const selectCounter = createFeatureSelector<AppState, State>(counterFeatureKey)
const selectCount = createSelector(selectCounter, state => state.count) 내보내기7. 컴포넌트 클래스는 Action을 트리거하고 상태를 획득합니다.
"@ngrx/store"에서 { 선택, 저장 } 가져오기
"rxjs"에서 { Observable } 가져오기
"./store"에서 { AppState } 가져오기
"./store/actions/counter.actions"에서 { 감소, 증가 } 가져오기
"./store/selectors/counter.selectors"에서 { selectCount } 가져오기
내보내기 클래스 AppComponent {
개수: 관찰 가능<숫자>
constructor(개인 저장소: Store<AppState>) {
this.count = this.store.pipe(select(selectCount))
}
증분() {
this.store.dispatch(증분())
}
감소() {
this.store.dispatch(감소())
}
}8. 컴포넌트 템플릿 표시 상태
<버튼(클릭)="증분()">+</버튼>
<span>{{ 비동기 }}</span>
<버튼(클릭)="감소()">-</버튼>1. Action을 트리거할 때 구성 요소의 디스패치를 사용하여 매개 변수를 전달하면 매개 변수가 결국 Action 개체에 배치됩니다.
this.store.dispatch(increment({ count: 5 }))2. Action Creator 기능을 생성할 때 매개변수를 얻고 매개변수 유형을 지정합니다.
"@ngrx/store"에서 { createAction, props } 가져오기
const increment = createAction("increment", props<{ count: number }>()) 내보내기내보내기 선언 함수 props<P 확장 객체>(): Props<P>;
3. Reducer의 Action 객체를 통해 매개변수를 얻습니다.
const 감속기 내보내기 = createReducer(
초기 상태,
on(증가, (상태, 동작) => ({ 개수: state.count + action.count }))
)MetaReducer는 Action -> Reducer 사이의 후크로, 개발자가 Action(일반 Reducer 함수 호출 전에 호출됨)을 전처리할 수 있도록 해줍니다.
function debug(reducer: ActionReducer<any>): ActionReducer<any> {
반환 함수(상태, 동작) {
반환 감속기(상태, 동작)
}
}
const MetaReducers 내보내기: MetaReducer<AppState>[] = !environment.production
?[디버그]
: []요구 사항: 페이지에 버튼을 추가한 후 값이 증가할 때까지 1초 정도 지연하세요.
1. 컴포넌트 템플릿에 비동기 값 증가를 위한 버튼을 추가합니다. 버튼을 클릭하면 increment_async 메서드가 실행됩니다.
<button (click)="increment_async()">비동기</button>
2. increment_async 메서드를 구성 요소 클래스에 추가하고 작업을 트리거하여 메서드에서 비동기 작업을 수행합니다.
increment_async() {
this.store.dispatch(increment_async())
}3. 액션 파일에서 비동기 작업을 수행하기 위한 액션을 추가합니다.
const increment_async = createAction("increment_async") 내보내기4. Effect를 생성하고, Action을 수신하고, Side Effect를 수행하고, 계속해서 Action을 트리거합니다.
ng g effect store/effects/counter --root --module app.module.ts --skipTests
Effect 함수는 @ngrx/효과 모듈에서 제공되므로 관련 모듈 종속성을 루트 모듈로 가져와야 합니다.
"@angular/core"에서 { 주입 가능 } 가져오기
"@ngrx/효과"에서 { Actions, createEffect, ofType } 가져오기
"../actions/counter.actions"에서 { 증가, increment_async } 가져오기
"rxjs/operators"에서 { mergeMap, map } 가져오기
"rxjs"에서 { 타이머 } 가져오기
// 효과 생성
// Effect를 생성하는데 사용되며, Effect는 Side Effect를 수행하는데 사용됩니다.
// 메소드 호출 시 콜백 함수를 전달하고, 콜백 함수에 Observable 객체를 반환합니다. Side Effect가 실행된 후 트리거되는 Action 객체입니다. // 콜백 함수의 반환 값은 createEffect 내부에서 계속 반환됩니다. 메서드 및 최종 반환 값은 Effect 클래스의 속성에 저장됩니다. // Effect 클래스를 인스턴스화한 후 NgRx는 부작용 클래스 속성을 구독하고 트리거할 Action 개체를 얻습니다. 그리고 액션을 트리거합니다.
//행위
// 구성요소가 Action을 트리거할 때 Effect는 Actions 서비스를 통해 Action을 수신해야 하므로 Effect 클래스에서는 Actions 서비스 클래스의 인스턴스 객체가 생성자 매개변수를 통해 // 인스턴스를 Effect 클래스에 주입합니다. Actions 서비스 클래스의 객체는 Observable입니다. Action이 트리거되면 Action 객체 자체가 // ofType 데이터 스트림으로 방출됩니다.
// 대상 Action 객체를 필터링합니다.
// 매개변수는 대상 Action의 Action Creator 함수입니다. // 대상 Action 객체가 필터링되지 않으면 이번에는 데이터 스트림이 계속 전송되지 않습니다. // 대상 Action 객체가 필터링되면 Action 객체가 전송됩니다. @Injectable() 데이터 스트림으로 계속 전송됩니다.
내보내기 클래스 CounterEffects {
생성자(비공개 작업: 작업) {
// this.loadCount.subscribe(console.log)
}
loadCount = createEffect(() => {
this.actions.pipe(
ofType(increment_async),
mergeMap(() => 타이머(1000).pipe(map(() => 증분({ 개수: 10 }))))
)
})
}1. 개요
엔터티는 엔터티로 번역되며 엔터티는 컬렉션의 데이터 조각입니다.
NgRx는 엔터티 어댑터 개체를 제공하며, 그 목적은 개발자가 엔터티를 운영하는 효율성을 높이는 것입니다.
2. 코어
1. EntityState: 엔터티 유형 인터페이스
/*
{
ID: [1, 2],
엔터티: {
1: { ID: 1, 제목: "Hello Angular" },
2: { ID: 2, 제목: "Hello NgRx" }
}
}
*/
내보내기 인터페이스 State는 EntityState<Todo> {}를 확장합니다.2. createEntityAdapter: 엔터티 어댑터 객체 생성
3. EntityAdapter: 엔터티 어댑터 객체 유형 인터페이스
const 어댑터 내보내기: EntityAdapter<Todo> = createEntityAdapter<Todo>()
// 초기 상태를 가져옵니다. 객체 매개변수를 전달할지 여부는 // {ids: [], 엔터티: {}}입니다.
const 초기화 상태 내보내기: 상태 = 어댑터.getInitialState()3. 인스턴스 방법
https://ngrx.io/guide/entity/adapter#adapter-collection-methods
4. 선택기
// selectTotal은 데이터 항목 수를 가져옵니다. // selectAll은 모든 데이터를 가져와 배열 형태로 표시합니다. // selectEntities는 엔터티 컬렉션을 가져와 사전 형태로 표시합니다. // selectIds는 id 컬렉션을 가져와 표시합니다. 배열 형식입니다. const { selectIds, selectEntities, selectAll, selectTotal } = Adapter .getSelectors();내보내기 const selectTodo = createFeatureSelector<AppState, State>(todoFeatureKey) const selectTodos = createSelector(selectTodo, selectAll) 내보내기
1. 라우팅 상태 동기화
1) 모듈 소개
"@ngrx/router-store"에서 { StoreRouterConnectingModule } 가져오기
@NgModule({
수입: [
StoreRouterConnectingModule.forRoot()
]
})
내보내기 클래스 AppModule {}2) 라우팅 상태를 Store에 통합
"@ngrx/router-store"에서 fromRouter로 * 가져오기
내보내기 인터페이스 AppState {
라우터: fromRouter.RouterReducerState
}
const 감속기 내보내기: ActionReducerMap<AppState> = {
라우터: fromRouter.routerReducer
}2. 라우팅 상태를 얻기 위한 선택기를 생성합니다.
// router.selectors.ts
"@ngrx/store"에서 { createFeatureSelector } 가져오기
".."에서 { AppState } 가져오기
"@ngrx/router-store"에서 { RouterReducerState, getSelectors } 가져오기
const selectRouter = createFeatureSelector<AppState, RouterReducerState>(
"라우터"
)
수출 const {
// 현재 경로와 관련된 정보를 가져옵니다(라우팅 매개변수, 라우팅 구성 등).
현재 경로 선택,
// 주소 표시줄의 # 숫자 뒤의 콘텐츠를 가져옵니다. selectFragment,
// 라우팅 쿼리 매개변수 가져오기 selectQueryParams,
// 특정 쿼리 매개변수 가져오기 selectQueryParam('name')
selectQueryParam,
// 동적 라우팅 매개변수 가져오기 selectRouteParams,
// 특정 동적 라우팅 매개변수 가져오기 selectRouteParam('name')
selectRouteParam,
// 경로 사용자 정의 데이터 가져오기 selectRouteData,
// 경로 selectUrl의 실제 액세스 주소를 가져옵니다.
} = getSelectors(selectRouter) // home.comComponent.ts
"@ngrx/store"에서 { 선택, 저장 } 가져오기
"src/app/store"에서 {AppState} 가져오기
"src/app/store/selectors/router.selectors"에서 { selectQueryParams } 가져오기
내보내기 클래스 AboutComponent {
constructor(개인 저장소: Store<AppState>) {
this.store.pipe(select(selectQueryParams)).subscribe(console.log)
}
}