我是NgRX商店的新手。我在使用NgRx商店将票证数据放入票证组件时遇到问题。
我使用效果模块通过 ticketService
中的http get方法检索异步票证我不确定如何配置商店和选择器以获取票证详细信息。提供stackblitz url重现该问题。预先感谢。
https://stackblitz.com/edit/ngrx-demo-ticket
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpClientModule} from '@angular/common/http';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
import { TicketsComponent } from './tickets/tickets.component';
import { TicketsService } from './tickets.service';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { environment } from './environment/environment';
import {TicketReducer} from './store/ticket.reducers';
import {TicketEffects} from './store/ticket.effects';
@NgModule({
imports: [ BrowserModule, FormsModule, HttpClientModule,
StoreModule.forRoot(TicketReducer, {}),
EffectsModule.forRoot([TicketEffects]),
!environment.production ? StoreDevtoolsModule.instrument() : [],
],
declarations: [ AppComponent, HelloComponent, TicketsComponent ],
bootstrap: [ AppComponent ],
providers: [TicketsService]
})
export class AppModule { }
tickets.component.ts
import { Component, OnInit } from '@angular/core';
import { TicketsService } from '../tickets.service';
import { of, Observable, pipe } from 'rxjs';
import { Ticket } from '../models/ticket';
import { map, catchError, tap } from 'rxjs/operators';
import { Store, select } from '@ngrx/store';
import { AppState } from '../models/app.state';
import { selectTickets } from '../store/ticket.reducers';
import * as ticketActions from '../store/ticket.actions';
@Component({
selector: 'app-tickets',
templateUrl: './tickets.component.html',
styleUrls: ['./tickets.component.css']
})
export class TicketsComponent implements OnInit {
tickets$: Observable<Ticket[]>;
constructor(private store: Store<AppState>) {
this.tickets$ = this.store.select(pipe(selectTickets));
}
ngOnInit() {
this.store.dispatch(new ticketActions.loadTicketsAction());
this.tickets$.pipe(
// Getting tickets as undefined
tap(tickets => console.log('Store Tickets', tickets)),
map((data) => {
if (data && data !== null) {
data[6].assignee = '<a href="javascript:void(0);" class="btn btn-link">John Mike</a>';
return data;
}
}),
catchError(error => {
return of([]);
})
).subscribe(tickets => {
console.log('Store tickets', tickets)
});
}
}
app.state.ts
import { Ticket } from '../models/ticket';
export interface AppState {
readonly tickets: Ticket[];
}
ticket.ts
export interface Ticket {
id: string;
applicationName?: string;
category?: string;
subject: string;
description?: string;
status: string;
priority: string;
assignee: string;
platform?: string;
dueDate: string;
}
ticket.action.ts
import { Action } from '@ngrx/store';
import * as types from './action.types';
import { Ticket } from '../models/ticket';
export class loadTicketsAction implements Action {
readonly type = types.LOAD_TICKETS;
}
export class loadTicketsSuccessAction implements Action {
readonly type = types.LOAD_TICKETS_SUCCESS;
constructor(public payload: Ticket[]) {}
}
export type Actions =
loadTicketsAction |
loadTicketsSuccessAction;
ticket.reducers.ts
import * as ticketActions from './ticket.actions';
import * as types from './action.types';
import { AppState } from '../models/app.state';
export const initialState: AppState = {
tickets: []
}
export function TicketReducer(state = initialState, action: ticketActions.Actions):AppState {
switch(action.type) {
case types.LOAD_TICKETS_SUCCESS: {
return {...state, tickets: action.payload };
}
default:
return state;
}
}
export const selectTickets = (state: AppState) => state.tickets;
ticket.effects.ts
import { Injectable } from "@angular/core";
import { TicketsService } from "../tickets.service";
import { Effect, Actions, ofType } from '@ngrx/effects';
import { map, mergeMap } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { Action } from '@ngrx/store';
import * as ticketActions from './ticket.actions';
import * as types from './action.types';
@Injectable({
providedIn: 'root'
})
export class TicketEffects {
constructor(private ticketsService: TicketsService,
private actions$: Actions
) { }
@Effect() loadTickets$: Observable<Action> = this.actions$.pipe(
ofType<ticketActions.loadTicketsAction>(types.LOAD_TICKETS),
mergeMap(() => this.ticketsService.getAllTickets().pipe(
map(tickets => {
return (new ticketActions.loadTicketsSuccessAction(tickets))
})
))
)
}
答案 0 :(得分:1)
问题似乎出在您的效果上。您需要分派操作而不返回它。所以代替:
map(tickets => {
return (new ticketActions.loadTicketsSuccessAction(tickets))
})
执行此操作:
map(tickets => {
this.store.dispatch(new ticketActions.loadTicketsSuccessAction(tickets))
})
还将其添加到选择器中,并确保导入“ selectTickets $”。如果要从存储中获取数据,可以使用以下模式:
export const selectTicketsState = createFeatureSelector<TicketsState>('tickets');
export const getTickets = (state: AppState) => state.tickets;
export const selectTickets$ = createSelector(selectTicketsState, getTickets);
编辑:
好吧,我修改了堆栈闪电使其可以正常工作,说实话,我在那里做了很多更改,所以我无法完全适应它们。很多事情以错误的方式损坏/完成:
https://stackblitz.com/edit/ngrx-demo-ticket-uh4hnw
我建议您先看一个教程,第一次关注他,然后再进行更多尝试。
我还建议先通过我的Stackblitz,然后再进行比较,以便比较并找出问题所在。
祝你好运! 我推荐