[Angular] NgRx/effect, why to use it?
See the current implementaion of code, we have a smart component, and inside the smart component we are using both 'serivce' and 'store'.
In the large application, what we really want is one service to handle the application state instead of two or more. And also we need response to the user action to get new data, all the requirements actaully can be handled by 'Store'.
import {Component, OnInit} from '@angular/core';
import {Store} from '@ngrx/store';
import {ThreadsService} from "../services/threads.service";
import {AppState} from "../store/application-state";
import {AllUserData} from "../../../shared/to/all-user-data";
import {LoadUserThreadsAction} from "../store/actions";
import {Observable} from "rxjs";
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/skip';
import {values, keys, last} from 'ramda';
import {Thread} from "../../../shared/model/thread.interface";
import {ThreadSummary} from "./model/threadSummary.interface"; @Component({
selector: 'thread-section',
templateUrl: './thread-section.component.html',
styleUrls: ['./thread-section.component.css']
})
export class ThreadSectionComponent implements OnInit { userName$: Observable<string>;
counterOfUnreadMessages$: Observable<number>;
threadSummary$: Observable<ThreadSummary[]>; constructor(private store: Store<AppState>,
private threadsService: ThreadsService) { this.userName$ = store.select(this.userNameSelector); this.counterOfUnreadMessages$ = store.select(this.unreadMessageCounterSelector); this.threadSummary$ = store.select(this.mapStateToThreadSummarySelector.bind(this))
} mapStateToThreadSummarySelector(state: AppState): ThreadSummary[] {
const threads = values<Thread>(state.storeData.threads);
return threads.map((thread) => this.mapThreadToThreadSummary(thread, state));
} mapThreadToThreadSummary(thread: Thread, state: AppState): ThreadSummary {
const names: string = keys(thread.participants)
.map(participantId => state.storeData.participants[participantId].name)
.join(', ');
const lastMessageId: number = last(thread.messageIds);
const lastMessage = state.storeData.messages[lastMessageId];
return {
id: thread.id,
participants: names,
lastMessage: lastMessage.text,
timestamp: lastMessage.timestamp
};
} userNameSelector(state: AppState): string {
const currentUserId = state.uiState.userId;
const currentParticipant = state.storeData.participants[currentUserId]; if (!currentParticipant) {
return "";
} return currentParticipant.name;
} unreadMessageCounterSelector(state: AppState): number {
const currentUserId: number = state.uiState.userId; if (!currentUserId) {
return ;
} return values<Thread>(state.storeData.threads)
.reduce(
(acc: number, thread) => acc + (thread.participants[currentUserId] || )
, );
} ngOnInit() { this.threadsService.loadUserThreads()
.subscribe((allUserData: AllUserData) => {
this.store.dispatch(new LoadUserThreadsAction(allUserData))
});
} }
So what we want to do to improve the code is to "remove the service from the component, let it handle by ngrx/effect" lib.
Here instead we call the service to get data, we will dispatch an action call 'LoadUserTreadsAction', and inside this action, will have side effect either "UserTreadsLoadSuccess" or "UserTreadsLoadError".
Create a effect service:
import {Injectable} from '@angular/core';
import {Action} from '@ngrx/store';
import {Actions, Effect} from "@ngrx/effects";
import {ThreadsService} from "../../services/threads.service";
import {LOAD_USER_THREADS_ACTION, LoadUserThreadsSuccess} from "../actions";
import {Observable} from "rxjs"; @Injectable()
export class LoadUserThreadsEffectService { constructor(private action$: Actions, private threadsService: ThreadsService) {
} @Effect()
userThreadsEffect$: Observable<Action> = this.action$
.ofType(LOAD_USER_THREADS_ACTION) // only react for LOAD_USER_THREADS_ACTION
.switchMap(() => this.threadsService.loadUserThreads()) // get data from service
.map((allUserData) => new LoadUserThreadsSuccess(allUserData)) // After get data, dispatch success action
}
And of course, we need to import the lib:
..
import {EffectsModule} from "@ngrx/effects";
import {LoadUserThreadsEffectService} from "./store/effects/load-user-threads.service"; @NgModule({
declarations: [
AppComponent
],
imports: [
..
EffectsModule.run(LoadUserThreadsEffectService),
],
providers: [
ThreadsService
],
bootstrap: [AppComponent]
})
export class AppModule {
}
We need to change reudcer, instead of add case for 'LOAD_USER_THREAD_ACTION', we should do 'LOAD_USER_THREADS_SUCCESS':
export function storeReducer(state: AppState = INITIAL_APPLICATION_STATE, action: Action): AppState { switch(action.type) {
case LOAD_USER_THREADS_SUCCESS:
return handleLoadUserThreadsAction(state, action);
default:
return state;
}
}
Last, in our component, we dispatch 'LoadUserThreadsAction':
ngOnInit() { this.store.dispatch(new LoadUserThreadsAction())
}
[Angular] NgRx/effect, why to use it?的更多相关文章
- [Angular] How to get Store state in ngrx Effect
For example, what you want to do is navgiate from current item to next or previous item. In your com ...
- [Angular] Ngrx/effects, Action trigger another action
@Injectable() export class LoadUserThreadsEffectService { constructor(private action$: Actions, priv ...
- ngRx 官方示例分析 - 6 - Effect
@ngrx/effect 前面我们提到,在 Book 的 reducer 中,并没有 Search 这个 Action 的处理,由于它需要发出一个异步的请求,等到请求返回前端,我们需要根据返回的结果来 ...
- [转]VS Code 扩展 Angular 6 Snippets - TypeScript, Html, Angular Material, ngRx, RxJS & Flex Layout
本文转自:https://marketplace.visualstudio.com/items?itemName=Mikael.Angular-BeastCode VSCode Angular Typ ...
- 手把手教你用ngrx管理Angular状态
本文将与你一起探讨如何用不可变数据储存的方式进行Angular应用的状态管理 :ngrx/store——Angular的响应式Redux.本文将会完成一个小型简单的Angular应用,最终代码可以在这 ...
- 如何在AngularX 中 使用ngrx
ngrx 是 Angular框架的状态容器,提供可预测化的状态管理. 1.首先创建一个可路由访问的模块 这里命名为:DemopetModule. 包括文件:demopet.html.demopet.s ...
- ngRx 官方示例分析 - 4.pages
Page 中通过构造函数注入 Store,基于 Store 进行数据操作. 注意 Component 使用了 changeDetection: ChangeDetectionStrategy.OnPu ...
- ngRx 官方示例分析 - 3. reducers
上一篇:ngRx 官方示例分析 - 2. Action 管理 这里我们讨论 reducer. 如果你注意的话,会看到在不同的 Action 定义文件中,导出的 Action 类型名称都是 Action ...
- angular版聊天室|仿微信界面IM聊天|NG2+Node聊天实例
一.项目介绍 运用angular+angular-cli+angular-router+ngrx/store+rxjs+webpack+node+wcPop等技术实现开发的仿微信angular版聊天室 ...
随机推荐
- 找不到或无法载入主类 org.jivesoftware.openfire.starter.ServerStarter
刚接触openfire的配置就出现了这个错误.解决方法非常easy,忘记了将openfire的源文件加入到user entries中了
- Android中的帧动画与补间动画的使用
前言 在日常开发中,我们有时候须要一些好看的动画效果,这时能够充分利用Android提供的这几种动画来实现. Android提供了3种类型的动画: 补间动画:补间动画能够应用于View,让你能够定义一 ...
- cx_Oracle
cx_Oracle 安装 pip install cx_Oracle 只是我没用那个安装成功过.我找了rpm 包. http://nchc.dl.sourceforge.net/project/cx- ...
- LOJ 6229 LCM / GCD (杜教筛+Moebius)
链接: https://loj.ac/problem/6229 题意: \[F(n)=\sum_{i=1}^n\sum_{j=1}^i\frac{\mathrm{lcm}(i,j)}{\mathrm{ ...
- Flask项目之手机端租房网站的实战开发(七)
说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...
- JVM route
http://www.linuxidc.com/Linux/2013-06/86446.htm
- 8.Swift教程翻译系列——控制流之条件
3.条件语句 常常会须要依据不同的情况来运行不同的代码. 你可能想要在错误发生的时候运行一段额外的代码,或者当某个值变得太高或者太低的时候给他输出出来.要实现这些需求,你能够使用条件分支. Swift ...
- css页面滚动条出现时防止页面跳动的方法
大家写页面时应该都遇到过一个问题,尤其是写单页面应用的时候, 在有滚动条页面和没有滚动条页面之间相互跳转时, 你页面的主体内容会向左或者向右抖一下,让强迫症看了很不舒服. 现在就来解救一下强迫症: 方 ...
- java中Arrays类的应用
java.util.Arrays类能方便地操作数组,它提供的所有方法都是静态的.具有以下功能: ² 给数组赋值:通过fill方法. ² 对数组排序:通过sort方法,按升序. ² 比较数组:通过equ ...
- 【LCS】POJ1458Common Subsequence
题目链接:http://poj.org/problem?id=1458 这是一道最长公共子序列的模板题: #include<iostream> #include<string> ...