Amr*_*uta 2 typescript ngrx-effects angular ngrx-store angular8
我知道问题的标题含糊不清,但不幸的是我不完全知道是什么导致了我的问题,所以请耐心等待。
我刚刚开始处理一个小的 Angular 8 任务,它也使用 NgRx/Store 和 NgRx/Effects。我正在Book使用getBooks函数获取一组对象。我的代码如下(没有把输入端口放在任何地方只是为了使代码部分更短)
book.component.ts
export class BookComponent {
constructor(private booksService: BooksService, public store: Store<BooksState>) {
this.books$ = store.pipe(select('books'));
}
books$: Observable<BooksState>;
BooksSubscription: Subscription;
booksList: Book[];
ngOnInit() {
this.BooksSubscription = this.books$
.pipe( map(x => { this.booksList = x.Books; }) ).subscribe();
this.store.dispatch(BooksActions.BeginGetBooksAction())
}
}
Run Code Online (Sandbox Code Playgroud)
书.service.ts
import { Injectable } from '@angular/core';
import booksData from "../../books.json";
@Injectable()
export class BooksService {
constructor() { }
getBooks(){
return booksData;
}
}
Run Code Online (Sandbox Code Playgroud)
booksData是Book我从json文件导入的类型对象的数组。
书.action.ts
import { createAction, props } from "@ngrx/store";
import { Book } from "./book";
export const GetBooksAction = createAction("GetBooks");
export const BeginGetBooksAction = createAction("BeginGetBooks");
export const SuccessGetBooksAction = createAction( "SuccessGetBooks", props<{ payload: Book[] }>());
Run Code Online (Sandbox Code Playgroud)
book.reducer.ts
import { Action, createReducer, on } from "@ngrx/store";
import * as BooksActions from "./book.action";
import { Book } from "./book";
export interface BooksState {
Books: Book[];
}
const initialState: BooksState = {
Books: []
};
const booksReducer = createReducer(
initialState,
on(BooksActions.GetBooksAction, state => state))
on(BooksActions.SuccessGetBooksAction, (state: BooksState, { payload }) => {
console.log(payload)
return { ...state, Books: payload };
});
export function reducer(state: BooksState | undefined, action: Action) {
return booksReducer(state, action);
}
Run Code Online (Sandbox Code Playgroud)
book.effect.ts
现在这就是我迷失的地方。我在 NgRx 文档上找到了一个参考代码,我根据它编写了代码,但它不起作用
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { Action } from '@ngrx/store';
import { Observable } from 'rxjs';
import { map, mergeMap} from 'rxjs/operators';
import * as BooksActions from './book.action';
import { Book } from './book';
import { BooksService } from './book.service';
@Injectable()
export class BooksEffects {
constructor(private action$: Actions, private booksService: BooksService) { }
GetBooks$: Observable<Action> = createEffect(() =>
this.action$.pipe(
ofType(BooksActions.BeginGetBooksAction),
mergeMap(
() => this.booksService.getBooks().pipe(
map((booksData: Book[]) => {
return BooksActions.SuccessGetBooksAction({ payload: booksData });
}))
)
)
)
);
}
Run Code Online (Sandbox Code Playgroud)
我在编译过程中遇到以下错误。错误在我有的地方pipe functions
error TS2322: Type 'Observable<unknown>' is not assignable to type 'Observable<Action> | ((...args: any[])
=> Observable<Action>)'.
Type 'Observable<unknown>' is not assignable to type 'Observable<Action>'.
Property 'type' is missing in type '{}' but required in type 'Action'.
Run Code Online (Sandbox Code Playgroud)
error TS2339: Property 'pipe' does not exist on type '{ "isbn": string; "title": string; "subtitle": string; "author": string; "published": string; "publisher": string; "pages": number; "description": string; "website": string; }[]'.
另外,我已经加入StoreModule.forRoot({ books: reducer})并EffectsModule.forRoot([BooksEffects])到imports并添加BookService到Providers在app.module.ts
您的代码中有两个错误。
MergeMap 使用不当
您this.booksService.getBooks()似乎没有返回Observable. 在这种情况下,您要使用map代替mergeMap:
GetBooks$: Observable<Action> = createEffect(() =>
this.action$.pipe(
ofType(BooksActions.BeginGetBooksAction),
map(() => this.booksService.getBooks()),
map(payload => BooksActions.SuccessGetBooksAction({ payload })
)
);
Run Code Online (Sandbox Code Playgroud)
详细说明,mergeMap当您想从一个 Observable 切换到另一个 Observable(类似于switchMap)时使用。回调预计会返回一个 Observable,然后mergeMap可以订阅。for 的回调map预计会返回一个值并将该值包装到一个新的 Observable 中。由于您getBooks()没有返回 Observable,mergeMap无法订阅它,TypeScript 知道这一点并抛出所述错误。或者,您也可以getBooks()改为返回一个 Observable(如果您以后想从 HTTP 请求中获取这些,这将返回一个 Observable,这将是一种可行的方法。
减速器中的括号错误
此外,经过进一步检查,您的效果和减速器实际上正在运行。但是您在减速器中的括号有一个小错误。看这个:
const booksReducer = createReducer(
initialState,
on(BooksActions.GetBooksAction, state => state)) // <---- This ")" is closing your "createReducer" function!
on(BooksActions.SuccessGetBooksAction, (state: BooksState, { payload }) => {
console.log(payload)
return { ...state, Books: payload };
});
Run Code Online (Sandbox Code Playgroud)
所以如果你格式化它以反映它在做什么,你写道:
const booksReducer = createReducer(
initialState,
on(BooksActions.GetBooksAction, state => state)
)
// You "on" function is actually outside "createReducer" effectively NEVER being triggered (but this is syntactically correct so a very tricky error)
on(BooksActions.SuccessGetBooksAction, (state: BooksState, { payload }) => {
console.log(payload)
return { ...state, Books: payload };
});
Run Code Online (Sandbox Code Playgroud)
所以你只需要修复那个:
const booksReducer = createReducer(
initialState,
on(BooksActions.GetBooksAction, state => state),
on(BooksActions.SuccessGetBooksAction, (state: any, { payload }) => {
console.log('Reducer is running, value is:', payload)
return { ...state, Books: payload };
})
);
Run Code Online (Sandbox Code Playgroud)
这是一个有效的Stackblitz。查看控制台以查看正在触发的所有内容。
| 归档时间: |
|
| 查看次数: |
1301 次 |
| 最近记录: |