angular - Angular Ngrx 商店 - store.select('selector name') 预计会返回书籍列表,但它返回一个不可迭代的列表
问题描述
我在这里做错了什么?这是我第一次尝试使用状态管理。
我尝试时的最终输出。从状态中获取它
减速器:
import {createReducer, on} from '@ngrx/store';
import {getBooksSuccess} from './book-list.actions';
import {Book} from '../../models/book.model';
const initialState: Array<Book> = [];
export interface BookState {
bookList: Book[];
}
export const bookReducer = createReducer(
initialState,
on(getBooksSuccess, (state, action) => {
return {
...state,
books: action,
};
})
);
export function BookReducer(state, action) {
return bookReducer(state, action);
}
行动:
import {createAction} from '@ngrx/store';
import {Book} from '../../models/book.model';
export const FETCH_BOOKS_START = '[Books] books start';
export const FETCH_BOOKS_SUCCESS = '[Books] books Success';
export const getBooks = createAction(
FETCH_BOOKS_START
);
export const getBooksSuccess = createAction(
FETCH_BOOKS_SUCCESS,
(books: ReadonlyArray<Book>) => books
);
影响:
fetchBooks$ = createEffect(() => {
return this.actions$.pipe(
ofType(getBooks),
mergeMap(() => {
return this.bookService.getBooks().pipe(
map((bookList) => {
this.books = this.bookService.mapToBooksModel(bookList);
return getBooksSuccess(this.books);
})
);
})
);
});
服务等级
@Injectable({
providedIn: 'root',
})
export class BookService {
responseData: BookResponseData[];
bookList: Book[];
constructor(private http: HttpClient) {
}
getBooks(): Observable<BookResponseData[]> {
return this.http.get<BookResponseData[]>(
`./assets/books.json`,
);
}
mapToBooksModel(books: BookResponseData[]) {
this.bookList = books;
return this.bookList;
}
}
模型类
export interface Book {
id: string;
name: string;
author: string;
}
export interface BookResponseData {
id: string;
name: string;
author: string;
}
选择器:
import {BookState} from './book-list.reducer';
import {Book} from '../../models/book.model';
import {createSelector} from '@ngrx/store';
export const BOOK_STATE_NAME = 'bookList';
export const bookSelector = createSelector(
(state: BookState) => state.bookList,
(books: Array<Book>) => books
);
export class BookListComponent implements OnInit {
book$: Observable<Book[]>;
books: Book[];
constructor(private store: Store<BookState>) {
}
ngOnInit(): void {
this.store.dispatch(getBooks());
this.store.select(bookSelector).pipe().subscribe( books => {
this.books = books;
console.log(this.books);
});
}
解决方案
我想错误就在这里。您正在为 books 属性分配一个操作对象,但您只需要它的有效负载。您可以像这样分配它,也可以books: action.books
简单地解构操作对象。
export const bookReducer = createReducer(
initialState,
on(getBooksSuccess, (state, { books }) => {
return {
...state,
books
};
})
);
编辑:再次阅读您的问题时,我注意到可能值得解决的多个潜在问题。
// BookService
getBooks(): Observable<BookResponseData[]> {
return this.http.get<BookResponseData[]>(`./assets/books.json`)
.pipe(map(books) => {
this.bookList = books.map(b => {...b}); //create a copy, otherwise some weird reference issues might pop up
return this.bookList;
});
}
// no need for 'mapToBooksModel' function now
你的行为是以一种奇怪的方式定义的。我以前没见过,试试这个。
// books action
export const getBooksSuccess = createAction(
FETCH_BOOKS_SUCCESS,
props<{books: ReadonlyArray<Book>}>() // defines payload, books should be then accessible
);
你的效果还需要一些润色。为什么要将服务的结果存储在类属性 ( this.books
) 中。这可能会导致一些问题,当严格模式关闭时,您可以在不使用减速器的情况下重写状态。另外,getBooksSuccess
函数中发生了什么?
fectchBooks$ = createEffect(() =>
this.actions$.pipe(
ofType(getBooks),
concatMap(() => this.bookService.getBooks())
map((bookList) => getBooksSuccess(bookList))
)
);
推荐阅读
- flutter - 如何在颤动中创建带有下一个和上一个按钮的可滚动选项卡
- azure-functions - Azure Functions:消耗计划中插槽之间的内存和 CPU 分配
- python - 获取当前索引号 QStackedWidget
- python - Python:图形用户界面和后端
- javascript - 编译失败 - 反应
- html - 将图像添加到离子选择选项(离子选择)
- python - 运行 python 脚本写入文件的 Windows 任务计划程序
- javascript - How to use emojionearea library in webpack
- javascript - json-server 未显示 JSON 数据的 URL
- python - 用 Python 写一个 excel 文件