angular - Angular 使用 Akita 商店 ngOnInit 在首次加载时不起作用
问题描述
我的 Angular10 应用程序使用 Akita 商店时遇到问题。
当我在我的组件页面上启动/刷新我的应用程序时,我在我的组件上看到 LOADING。
但是,通过控制台,看起来商店已经加载了项目,并且我的 console.logs 在 onInit 中被触发。
当我在他们应该加载的页面上刷新应用程序时,它不会,它只会显示“正在加载”。但是,如果我单击此页面的路由器链接按钮,它将加载。
/models/post post.model.ts
export interface Post {
// fields here
}
/stores/post post.store.ts
export interface PostsState extends EntityState<Post, number> {
posts: Post[];
isLoaded: boolean;
}
export const getInitialState = () => {
return {
posts: [],
isLoaded: false,
};
};
@Injectable({
providedIn: 'root'
})
@StoreConfig({name: ‘postsStore'})
export class PostsStore extends EntityStore<PostsState> {
constructor() {
super(getInitialState());
}
}
/stores/user user.query.ts
@Injectable({ providedIn: 'root' })
export class PostsQuery extends QueryEntity<PostsState> {
constructor(protected store: PostsStore) {
super(store);
}
getPosts(): Observable<Post[]> {
return this.select(state => state.posts);
}
getLoaded():Observable<boolean> {
return this.select(state => state.isLoaded);
}
getIsLoading():Observable<boolean> {
return this.selectLoading();
}
}
import { ID } from '@datorama/akita';
服务/帖子posts.service.ts
@Injectable({ providedIn: 'root' })
export class PostsService {
private API_URL = `${environment.apiUrl}`;
constructor(private postsStore: PostsStore,
private http: HttpClient) {}
get() {
return this.http.get<Post[]>(`${this.API_URL}/posts`)
.pipe(
tap(entities => this.postsStore.set(entities))
);
}
add(post: Post) {
this.postsStore.add(post);
}
update(id, post: Partial<Post>) {
this.postsStore.update(id, post);
}
视觉/视觉.component.ts
ngOnInit(): void {
console.log('STARTING'); // on page initial this shows
this.postsQuery.getIsLoading().subscribe(res => this.loading = res);
this.postsQuery.getPosts().subscribe(res => this.posts = res);
this.postsQuery.getLoaded().pipe(
take(1),
filter(res => !res),
switchMap(() => {
this.postsStore.setLoading(true);
console.log(‘TEST ‘A); // on page initial this shows
return this.postsService.get();
})
).subscribe(res => {
this.postsStore.update(state => {
console.log(‘TEST ‘B); // on page initial this shows
return {
posts: res
};
});
this.postsStore.setLoading(false);
console.log(‘TEST’ C); // on page initial this shows
}, err => {
console.log(err);
this.postsStore.setLoading(false);
console.log(‘TEST ‘D); // This does not show
});
}
视觉/视觉.component.html
<div *ngIf="loading">
<p>
LOADING
</p>
</div>
<div *ngIf="!loading">
<div *ngFor="let post of posts>
{{post.name}}
<div>
</div>
解决方案
最好在 stackblitz 上有这个例子来尝试一下(如果不调试就很难解决问题)。
另外,我建议尝试添加console.log
订阅this.postsQuery.getIsLoading()
以更好地调试它。
但是,现在我看到两个选项:
尝试添加订阅
changeDetectorRef.detectChange()
;this.postsQuery.getIsLoading()
该问题可能与此问题有关https://github.com/datorama/akita/issues/653(参见 stackblitz 示例),其根本原因是在商店订阅中同步更新商店。
修复它的方法是延迟this.postsStore.setLoading(true);
(您可以尝试将其放入setTimeout()
或添加一些 rxjs 运算符)
推荐阅读
- ios - ViewController 根据具体记法推送到next
- reactjs - Reactjs:ReactTable css 不使用 js 文件中的导入加载 css
- parsing - 代码编译过程中需要什么符号表和AST?
- ios - epubjs-rn - 在 iOS 中突出显示文本
- java - Volley GET & Post JSONObject 请求到 TextView 中的 API 视图
- reactjs - 材质 UI - 如何更改 FormControlLabel 中标签的字体大小
- arrays - Angular 7:自定义类装饰器破坏组件范围
- mysql - 使用 Flutter/dart 设置 MySQL 以在移动/android 上进行本地开发和测试
- vba - 对象'_Global'的方法'工作表'失败 - 请帮助我
- postgresql - 使用 psql 命令在 COPY 语句中进行 Postgresql 动态查询