Angular daje świetne narzędzia do budowania aplikacji, a NgRx daje możliwość zarządzania aplikacją ze stanem. W tym artykule dzielę się kilkoma fragmentami kodu, które pomogą Ci wprowadzić @Effects do pracy z aplikacją CRUD.
Akcje
W pliku post.actions.ts tworzymy akcje takie jak
import {Action} from '@ngrx/store';
export enum PostActionTypes {
FetchPosts = '[POST] Fetch Posts',
FetchPostsError = '[POST] Fetch Posts Error',
SetPosts = '[POST] Set Posts',
CreatePost = '[POST] Create Post',
CreatePostError = '[POST] Create Post Error',
CreatePostSuccess = '[POST] Create Post Success',
UpdatePost = '[POST] Update Post',
UpdatePostError = '[POST] Update Post Error',
UpdatePostSuccess = '[POST] Update Post Success',
RemovePost = '[POST] Remove Post',
RemovePostError = '[POST] Remove Post Error',
RemovePostSuccess = '[POST] Remove Post Success',
FetchCurrentPost = '[POST] Fetch Current Post',
SetCurrentPost = '[POST] Set Current Post',
}
export class FetchPosts implements Action {
readonly type = PostActionTypes.FetchPosts;
constructor() {
}
}
export class FetchPostsError implements Action {
readonly type = PostActionTypes.FetchPostsError;
constructor(public payload) {
}
}
export class SetPosts implements Action {
readonly type = PostActionTypes.SetPosts;
constructor(public payload) {
}
}
export class CreatePost implements Action {
readonly type = PostActionTypes.CreatePost;
constructor(public payload) {
}
}
export class CreatePostError implements Action {
readonly type = PostActionTypes.CreatePostError;
constructor(public payload) {
}
}
export class CreatePostSuccess implements Action {
readonly type = PostActionTypes.CreatePostSuccess;
constructor(public payload) {
}
}
export class RemovePost implements Action {
readonly type = PostActionTypes.RemovePost;
constructor(public payload) {
}
}
export class RemovePostError implements Action {
readonly type = PostActionTypes.RemovePostError;
constructor(public payload) {
}
}
export class RemovePostSuccess implements Action {
readonly type = PostActionTypes.RemovePostSuccess;
constructor(public payload) {
}
}
export class UpdatePost implements Action {
readonly type = PostActionTypes.UpdatePost;
constructor(public payload) {
}
}
export class UpdatePostError implements Action {
readonly type = PostActionTypes.UpdatePostError;
constructor(public payload) {
}
}
export class UpdatePostSuccess implements Action {
readonly type = PostActionTypes.UpdatePostSuccess;
constructor(public payload) {
}
}
export class FetchCurrentPost implements Action {
readonly type = PostActionTypes.FetchCurrentPost;
constructor() {
}
}
export class SetCurrentPost implements Action {
readonly type = PostActionTypes.SetCurrentPost;
constructor(public payload) {
}
}
export type PostAction =
FetchPosts |
FetchPostsError |
SetPosts |
CreatePost |
CreatePostError |
CreatePostSuccess |
RemovePost |
RemovePostError |
RemovePostSuccess |
UpdatePost |
UpdatePostError |
UpdatePostSuccess |
FetchCurrentPost |
SetCurrentPost;
Więc mówiąc prosto, każda akcja ma swój wywołujący jak 'UpdatePost', następnie jeśli akcja się nie powiedzie, powinien być wywołany 'UpdatePostError', a jeśli Update się powiedzie, powinien być wywołany 'UpdatePostSuccess'.
Serwis
Serwis Post w pliku post.service.ts.
@Injectable({
providedIn: 'root'
})
export class PostService {
constructor(
private serverService: ServerService,
private store: Store<AppState>
) {}
getPosts = () => this.serverService.get(POSTS_URL);
addPost = (post) => this.serverService.post(POSTS_URL, post);
removePost = (post) => this.serverService.delete(POSTS_URL + post._id);
updatePost = (post) => this.serverService.put(POSTS_URL + post._id, post);
}
Jak widzisz, są cztery metody getPosts, addPost, removePost, updatePost. ServerService jest oparty na standardowych metodach HTTP GET/POST/DELETE/PUT.
W tym przypadku POSTS_URL to stały ciąg z URL do endpointu jak 'http://api.domain.com/posts'.
Fragmenty kodu CRUD oparte na @Effect()
@Effect() - Pobierz listę (posts)
Jak używać @Effect dla akcji Get
@Effect()
loadPosts$: Observable<Action> = this.actions$.pipe(
ofType(PostActionTypes.FetchPosts),
switchMap(() => {
return this.postService.getPosts()
.pipe(
switchMap((response: Response) => [
new SetPosts(response.data),
new StopLoading({error: null, msg: 'Posts loaded'})
]),
catchError(err => of(new FetchPostsError(err)))
);
})
);
@Effect() - Utwórz (post)
Jak używać @Effect dla akcji Create
@Effect()
createPosts$: Observable = this.actions$.pipe(
ofType(PostActionTypes.CreatePost),
switchMap((action) => {
return this.postService.addPost(action['payload'])
.pipe(
switchMap((response: Response) => [
new CreatePostSuccess(response.data),
new StopLoading({error: null, msg: 'Post loaded'})
]),
catchError(err => of(new CreatePostError(err)))
);
})
);
@Effect() - Aktualizuj (post)
Jak używać @Effect dla akcji Update
@Effect()
updatePost$: Observable = this.actions$.pipe(
ofType(PostActionTypes.UpdatePost),
switchMap((action) => {
return this.postService.updatePost(action['payload'])
.pipe(
switchMap((response: Response) => [
new UpdatePostSuccess(response.data),
new StopLoading({error: null, msg: 'Post updated'})
]),
catchError(err => of(new UpdatePostError(err)))
);
})
);
@Effect() - Usuń (post)
Jak używać @Effect dla akcji Delete
@Effect()
removePost$: Observable = this.actions$.pipe(
ofType(PostActionTypes.RemovePost),
switchMap((action) => {
return this.postService.removePost(action['payload'])
.pipe(
switchMap((response: Response) => [
new RemovePostSuccess(response.data),
new StopLoading({error: null, msg: 'Post removed'})
]),
catchError(err => of(new RemovePostError(err)))
);
})
);





