关于从 NgRx store 中选择数据的问题
Questions about selecting data from NgRx store
@Component({
selector: 'app-user',
styleUrls: ['./user.component.css'],
template: `
<button (click)="clickSearch('some keyword')">Search</button>
<div *ngIf="books$ | async as books">
<h5 *ngIf="hasSearched">No. of books: {{ books.length }}</h5>
<p *ngIf="hasSearched && !books.length">No books found</p>
<p *ngIf="!hasSearched">Please enter a search keyword to start searching for books.</p>
<h2 *ngFor="let book of books">{{ book.title }}</h2>
</div>
`
})
export class UserComponent {
constructor(private store: Store) {}
hasSearched: boolean = false;
books$ = this.store.select(BooksSelector.getBooks)
.pipe(
tap(data => console.log(data))
);
clickSearch(keyword: string) {
this.hasSearched = true;
this.store.dispatch(BooksActions.loadBooksFromApi(
{ q: keyword }
));
}
}
假设我有一个类似于上面的简化 Angular 组件代码。流量:
当我们第一次进入这个页面时,store.select() 语句立即 return 存储 []
的初始状态值。这将导致模板显示“未找到书籍”和“书籍数量 = 0”消息,这是我不想要的。所以为了防止它,我添加了 hasSearched
布尔值 属性 并改为显示“请输入...”消息。
单击“搜索”按钮时,hasSearched
属性 变为 true
,而 API 检索数据时,模板将简要显示“未找到书籍”和“书籍数量=0”消息。我不希望它以这种方式运行。我希望消息等待(通过隐藏)直到 API 调用完成。
当API调用完成后,图书列表正常出现在模板中,消息也正确显示。
在用户搜索某些内容并获得一些结果后,然后离开页面并 returns 到它,store.select() 语句将 return以前的商店价值。我不想要这个。我只是想让这个页面重新开始,没有书籍列表,只有消息“请输入搜索关键字开始搜索书籍。”。
我的问题针对第 2 点和第 4 点:
对于第 2 点,我是否应该添加另一个布尔值 属性 来检查加载状态?似乎有太多 *ngIf 标志。有没有更优雅的方式通过 NgRx 选择器来处理这个问题?
对于第 4 点,我该如何实现?是通过在 ngOnDestroy()
期间向商店推送一个空的 []
来强制清除 Books 状态吗?
点数2
我建议在你的减速器中添加另一个布尔值 hasSearched: boolean
,并从组件中删除 hasSearched
。
使用组件中的选择器订阅 hasSearched
。
当用户第一次进入该组件时,它应该是 undefined
。由此,您可以显示您的消息
<p *ngIf="(hasSearched | async) === undefined">
Please enter a search keyword to start searching for books.
</p>
当用户点击按钮时,您将调度您的操作 BooksActions.loadBooksFromApi
。在相同的 action/reducer 中,当 API 调用正在进行时,将字段 hasSearched 转换为 false
,
此 false
标志将阻止显示这两条消息:
<h5 *ngIf="(hasSearched | async)">No. of books: {{ books.length }}</h5>
<p *ngIf="(hasSearched | async) && !books.length">No books found</p>
完成后true
。作为参考,您的 state 和 reducer 将如下所示。
export interface BooksState {
books: any;
hasSearched: boolean;
}
export const initialState: BooksState = {
books: undefined,
hasSearched: undefined
};
reducer will cases 看起来像这样。
case BooksActionsTypes.loadBooksFromApi:
return {
...state,
hasSearched: false
};
case BooksActionsTypes.loadBooksFromApiSuccessful:
return {
...state,
books: action.payload.books
hasSearched: true
};
点数4
我的理解是正确的,通过在 ngOnDestroy()
上调度操作来清除状态。这与我使用的方式相同,当我想在下次访问同一组件时获得新状态时清除状态。这将类似于我在下面写的内容
case BooksActionsTypes.ClearState:
return {
...state,
books: undefined
hasSearched: undefined
};
@Component({
selector: 'app-user',
styleUrls: ['./user.component.css'],
template: `
<button (click)="clickSearch('some keyword')">Search</button>
<div *ngIf="books$ | async as books">
<h5 *ngIf="hasSearched">No. of books: {{ books.length }}</h5>
<p *ngIf="hasSearched && !books.length">No books found</p>
<p *ngIf="!hasSearched">Please enter a search keyword to start searching for books.</p>
<h2 *ngFor="let book of books">{{ book.title }}</h2>
</div>
`
})
export class UserComponent {
constructor(private store: Store) {}
hasSearched: boolean = false;
books$ = this.store.select(BooksSelector.getBooks)
.pipe(
tap(data => console.log(data))
);
clickSearch(keyword: string) {
this.hasSearched = true;
this.store.dispatch(BooksActions.loadBooksFromApi(
{ q: keyword }
));
}
}
假设我有一个类似于上面的简化 Angular 组件代码。流量:
当我们第一次进入这个页面时,store.select() 语句立即 return 存储
[]
的初始状态值。这将导致模板显示“未找到书籍”和“书籍数量 = 0”消息,这是我不想要的。所以为了防止它,我添加了hasSearched
布尔值 属性 并改为显示“请输入...”消息。单击“搜索”按钮时,
hasSearched
属性 变为true
,而 API 检索数据时,模板将简要显示“未找到书籍”和“书籍数量=0”消息。我不希望它以这种方式运行。我希望消息等待(通过隐藏)直到 API 调用完成。当API调用完成后,图书列表正常出现在模板中,消息也正确显示。
在用户搜索某些内容并获得一些结果后,然后离开页面并 returns 到它,store.select() 语句将 return以前的商店价值。我不想要这个。我只是想让这个页面重新开始,没有书籍列表,只有消息“请输入搜索关键字开始搜索书籍。”。
我的问题针对第 2 点和第 4 点:
对于第 2 点,我是否应该添加另一个布尔值 属性 来检查加载状态?似乎有太多 *ngIf 标志。有没有更优雅的方式通过 NgRx 选择器来处理这个问题?
对于第 4 点,我该如何实现?是通过在 ngOnDestroy()
期间向商店推送一个空的 []
来强制清除 Books 状态吗?
点数2
我建议在你的减速器中添加另一个布尔值 hasSearched: boolean
,并从组件中删除 hasSearched
。
使用组件中的选择器订阅 hasSearched
。
当用户第一次进入该组件时,它应该是 undefined
。由此,您可以显示您的消息
<p *ngIf="(hasSearched | async) === undefined">
Please enter a search keyword to start searching for books.
</p>
当用户点击按钮时,您将调度您的操作 BooksActions.loadBooksFromApi
。在相同的 action/reducer 中,当 API 调用正在进行时,将字段 hasSearched 转换为 false
,
此 false
标志将阻止显示这两条消息:
<h5 *ngIf="(hasSearched | async)">No. of books: {{ books.length }}</h5>
<p *ngIf="(hasSearched | async) && !books.length">No books found</p>
完成后true
。作为参考,您的 state 和 reducer 将如下所示。
export interface BooksState {
books: any;
hasSearched: boolean;
}
export const initialState: BooksState = {
books: undefined,
hasSearched: undefined
};
reducer will cases 看起来像这样。
case BooksActionsTypes.loadBooksFromApi:
return {
...state,
hasSearched: false
};
case BooksActionsTypes.loadBooksFromApiSuccessful:
return {
...state,
books: action.payload.books
hasSearched: true
};
点数4
我的理解是正确的,通过在 ngOnDestroy()
上调度操作来清除状态。这与我使用的方式相同,当我想在下次访问同一组件时获得新状态时清除状态。这将类似于我在下面写的内容
case BooksActionsTypes.ClearState:
return {
...state,
books: undefined
hasSearched: undefined
};