[英]How to dispatch an action before making an http call in Angular NgRx effects?
[英]Angular Ngrx - Effects not be called when dispatch Actions
我是 Ngrx 的新手,這是我項目的package.json
文件,我正在嘗試為我的項目實現調度登錄操作
{
"name": "shop-saleman",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^11.0.5",
"@angular/common": "^11.0.5",
"@angular/compiler": "^11.0.5",
"@angular/core": "^11.0.5",
"@angular/forms": "^11.0.5",
"@angular/localize": "^11.0.5",
"@angular/platform-browser": "^11.0.5",
"@angular/platform-browser-dynamic": "^11.0.5",
"@angular/router": "^11.0.5",
"@ng-bootstrap/ng-bootstrap": "9.1.3",
"@ngrx/effects": "^11.0.0",
"@ngrx/store": "^11.0.0",
"@types/socket.io-client": "^3.0.0",
"bootstrap": "4.5.0",
"ngx-cookie-service": "11.0.2",
"pretty-ms": "^7.0.1",
"rxjs": "^6.6.3",
"rxjs-compat": "^6.0.0",
"socket.io-client": "^4.5.1",
"tslib": "^2.0.3",
"zone.js": "^0.10.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.1100.4",
"@angular/cli": "^11.0.4",
"@angular/compiler-cli": "^11.0.5",
"@types/jasmine": "~3.6.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.19.9",
"codelyzer": "^6.0.1",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~5.1.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.4",
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"tslint": "~6.1.0",
"typescript": "~4.0.2"
}
}
這是存儲的src/store/index.ts
import { User } from "src/app/model/user.model";
export type AppState = {
user: User;
};
這是用戶操作的src/store/actions/user.action.ts
import { createAction, props } from "@ngrx/store";
import { User } from "src/app/model/user.model";
export const Types = {
LOGIN_PWD: "[USER] login with password",
LOGIN_SUC: "[USER] login successfully",
LOGIN_FAILED: "[USER] login failed",
};
export const lgPwd = createAction(
Types.LOGIN_PWD,
props<{ username: string; password: string }>()
);
export const lgSuc = createAction(
Types.LOGIN_SUC,
props<{ user: User; token: string }>()
);
export const lgFail = createAction(Types.LOGIN_FAILED, props<{ error: any }>());
這是src/store/effects/user.effects.ts
用於調度他們將調用的操作,我添加 console.log 以在傳遞時顯示用戶名和密碼:
import { Actions, ofType, createEffect, Effect } from "@ngrx/effects";
import { Injectable } from "@angular/core";
import { Store } from "@ngrx/store";
import { AppState } from "..";
import { UserService } from "src/app/services/auth.service";
import { lgPwd } from "../actions/user.actions";
import { catchError, map, switchMap } from "rxjs/operators";
import { from } from "rxjs";
@Injectable()
export class UserEffect {
constructor(
private action: Actions,
private store: Store<AppState>,
private user_service: UserService
) {}
lgPwdCall = createEffect(
() => {
return this.action.pipe(
ofType(lgPwd),
switchMap(({username, password}) => {
console.log('EFFECT ->', username, password)
return from(
this.user_service.lgPwd(username, password)
).pipe(
map((result) => {
console.log("success", result);
}),
catchError((err): any => {
console.log("err", err);
})
);
})
);
},
{ dispatch: false }
);
}
這是src/store/reducers/user.reducers.ts
定義了動作的減速器,我添加了 console.log 來顯示用戶名和密碼:
import { createReducer, on } from "@ngrx/store";
import { lgPwd } from "../actions/user.actions";
const initialState = {
currentUser: null,
token: "",
};
export const userReducer = createReducer(
initialState,
on(lgPwd, (state, { username, password }) => {
console.log("REDUCER ->", username, password);
state.currentUser = { username, password };
return state;
})
);
這是選擇器src/store/selectors/user.selectors.ts
:
import { createSelector } from "@ngrx/store";
import { AppState } from "..";
export const userState = (state: AppState) => state.user;
export const selectCurrentUser = createSelector(userState, (user) => user);
這是 User 類型的接口(如果需要) src/app/model/user.model.ts
:
export interface User {
addressList: string[];
avatar: string;
cardNumber: string;
email: string;
isActived: boolean;
mediaList: Media[];
phoneNumber: string;
role: string;
username: string;
zipCode: string;
_id: string;
}
export interface Media {
_id: string;
mimetype: string;
filename: string;
}
該操作在函數登錄的src/app/pages/login/login.component.ts
中調度:
import { Component, OnInit } from "@angular/core";
import { Router } from "@angular/router";
import { Store } from "@ngrx/store";
import { CookieService } from "ngx-cookie-service";
import { AppState } from "src/store";
import { lgPwd } from "src/store/actions/user.actions";
import { UserService } from "../../services/auth.service";
@Component({
selector: "app-login",
templateUrl: "./login.component.html",
styleUrls: ["./login.component.scss"],
})
export class LoginComponent implements OnInit {
email: string = "";
pwd: string = "";
isLogin: boolean = false;
visiblePwd: boolean = false;
constructor(
private api: UserService,
private route: Router,
private cookie_service: CookieService,
private store: Store<AppState>
) {}
ngOnInit(): void {}
login() {
this.isLogin = true;
this.store.dispatch(lgPwd({ username: this.email, password: this.pwd }));
}
togglePwd() {
return (this.visiblePwd = !this.visiblePwd);
}
}
這就是我在瀏覽器上切換檢查時得到的結果,如您所見,reducer 獲得了正確的用戶名和密碼,但它看不到任何 console.log,因為效果尚未被調用
請幫助我,這意味着很多,感謝您的寶貴時間,祝您有美好的一天
問題源於state.currentUser = { username, password };
, 在這里您嘗試分配{ username, password }
但currentUser
處於 ngrx 狀態,並且此對象狀態是只讀的。
而是創建一個新操作,在登錄成功時,將登錄用戶(可能是結果?)設置為狀態中的某個位置。
map((result) => {
console.log("success", result);
// create new action here OnLoginSuccess
}),
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.