Unable to patch the state with update to the store using NGXS. I keep seeing type error: cannot freeze
Unable to patch the state with update to the store using NGXS. I keep seeing type error: cannot freeze
我正在使用一个基本的 Angular 11 应用程序,它实现了身份验证(使用 AWS Cognito 和 Amplify)。我在这里要做的很简单。我正在使用内置的 AWS Amplify 方法进行身份验证。我正在使用 NGXS 来存储与身份验证相关的项目,例如令牌、用户信息等。
import { State, Action, StateContext, Selector } from '@ngxs/store';
import { AuthStateModel, defaultAuthState } from './auth.model';
import {
LoginAction,
AuthenticationCheckAction,
LogoutAction,
} from './auth.actions';
import { Auth } from 'aws-amplify';
import { environment } from 'src/environments/environment';
import { Injectable } from '@angular/core';
import { updateItem } from '@ngxs/store/operators';
@State<AuthStateModel>({
name: 'authState',
defaults: defaultAuthState,
})
@Injectable()
export class AuthState {
cognitoClientId = environment.cognitoClientId;
cognitoCallbackURL = environment.cognitoCallbackURL;
cognitoDomainName = environment.cognitoDomainName;
loginurl = `https://${this.cognitoDomainName}/login?response_type=code&client_id=${this.cognitoClientId}&redirect_uri=${this.cognitoCallbackURL}`;
@Selector()
static getIsLoggedIn(state: AuthStateModel) {
console.log('from getIsLoggedIn selector =>', state);
return state.isLoggedIn;
}
@Action(LoginAction)
login() {
window.location.assign(this.loginurl);
}
@Action(AuthenticationCheckAction)
checkLogin({ getState, patchState }: StateContext<AuthStateModel>) {
const state = getState();
Auth.currentAuthenticatedUser()
.then((currentUser) => {
const isLoggedIn = true;
const username = currentUser?.attributes?.name;
patchState({
currentUser,
isLoggedIn,
username,
});
})
.catch((err) => console.log(err));
return;
}
@Action(LogoutAction)
logout({ patchState }: StateContext<AuthStateModel>) {
Auth.signOut()
.then((data) => {
console.log(data);
patchState(defaultAuthState);
})
.catch((err) => console.log(err));
return;
}
}
一切正常,除了在 checkLogin 函数中调用 patchState 方法时,它会在浏览器控制台中抛出以下错误。:-
TypeError: Cannot freeze
at Function.freeze (<anonymous>)
at deepFreeze (ngxs-store.js:1869)
at ngxs-store.js:1884
at Array.forEach (<anonymous>)
at deepFreeze (ngxs-store.js:1874)
at ngxs-store.js:1884
at Array.forEach (<anonymous>)
at deepFreeze (ngxs-store.js:1874)
at ngxs-store.js:1884
at Array.forEach (<anonymous>)
奇怪的是,如果我从 pathState() 方法中注释掉 currentUser
的提及,错误就消失了。所以是状态里面对象的更新有问题。
ngxs-store.js 文件的此错误中引用的行包含以下代码。 1869 处的行是开头的 Object.freeze(o) 行:-
const deepFreeze = (/**
* @param {?} o
* @return {?}
*/
(o) => {
Object.freeze(o);
/** @type {?} */
const oIsFunction = typeof o === 'function';
/** @type {?} */
const hasOwnProp = Object.prototype.hasOwnProperty;
Object.getOwnPropertyNames(o).forEach((/**
* @param {?} prop
* @return {?}
*/
function (prop) {
if (hasOwnProp.call(o, prop) &&
(oIsFunction ? prop !== 'caller' && prop !== 'callee' && prop !== 'arguments' : true) &&
o[prop] !== null &&
(typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
!Object.isFrozen(o[prop])) {
deepFreeze(o[prop]);
}
}));
return o;
});
不够聪明,无法理解这里发生的事情。这是修补状态的简单尝试。状态模型如下:-
export class AuthStateModel {
isLoggedIn: Boolean;
currentUser: Object;
username: String;
}
export const defaultAuthState: AuthStateModel = {
isLoggedIn: false,
currentUser: {},
username: '',
};
我能做些什么来让它正常工作吗?
有时当我 运行 遇到这样的问题时,我无法更改对象,我只是克隆它。我通常为此使用 lodash 的 cloneDeep:
patchState({
currentUser: _.cloneDeep(currentUser),
isLoggedIn,
username,
});
此外,请尽量使您的状态可序列化。不熟悉 AWS Cognito 和 Amplify,但如果 currentUser 是一个对象,该对象具有稍后需要的方法和其他绑定到它的成员,那么我不会将 currentUser 对象存储在状态中。
我正在使用一个基本的 Angular 11 应用程序,它实现了身份验证(使用 AWS Cognito 和 Amplify)。我在这里要做的很简单。我正在使用内置的 AWS Amplify 方法进行身份验证。我正在使用 NGXS 来存储与身份验证相关的项目,例如令牌、用户信息等。
import { State, Action, StateContext, Selector } from '@ngxs/store';
import { AuthStateModel, defaultAuthState } from './auth.model';
import {
LoginAction,
AuthenticationCheckAction,
LogoutAction,
} from './auth.actions';
import { Auth } from 'aws-amplify';
import { environment } from 'src/environments/environment';
import { Injectable } from '@angular/core';
import { updateItem } from '@ngxs/store/operators';
@State<AuthStateModel>({
name: 'authState',
defaults: defaultAuthState,
})
@Injectable()
export class AuthState {
cognitoClientId = environment.cognitoClientId;
cognitoCallbackURL = environment.cognitoCallbackURL;
cognitoDomainName = environment.cognitoDomainName;
loginurl = `https://${this.cognitoDomainName}/login?response_type=code&client_id=${this.cognitoClientId}&redirect_uri=${this.cognitoCallbackURL}`;
@Selector()
static getIsLoggedIn(state: AuthStateModel) {
console.log('from getIsLoggedIn selector =>', state);
return state.isLoggedIn;
}
@Action(LoginAction)
login() {
window.location.assign(this.loginurl);
}
@Action(AuthenticationCheckAction)
checkLogin({ getState, patchState }: StateContext<AuthStateModel>) {
const state = getState();
Auth.currentAuthenticatedUser()
.then((currentUser) => {
const isLoggedIn = true;
const username = currentUser?.attributes?.name;
patchState({
currentUser,
isLoggedIn,
username,
});
})
.catch((err) => console.log(err));
return;
}
@Action(LogoutAction)
logout({ patchState }: StateContext<AuthStateModel>) {
Auth.signOut()
.then((data) => {
console.log(data);
patchState(defaultAuthState);
})
.catch((err) => console.log(err));
return;
}
}
一切正常,除了在 checkLogin 函数中调用 patchState 方法时,它会在浏览器控制台中抛出以下错误。:-
TypeError: Cannot freeze
at Function.freeze (<anonymous>)
at deepFreeze (ngxs-store.js:1869)
at ngxs-store.js:1884
at Array.forEach (<anonymous>)
at deepFreeze (ngxs-store.js:1874)
at ngxs-store.js:1884
at Array.forEach (<anonymous>)
at deepFreeze (ngxs-store.js:1874)
at ngxs-store.js:1884
at Array.forEach (<anonymous>)
奇怪的是,如果我从 pathState() 方法中注释掉 currentUser
的提及,错误就消失了。所以是状态里面对象的更新有问题。
ngxs-store.js 文件的此错误中引用的行包含以下代码。 1869 处的行是开头的 Object.freeze(o) 行:-
const deepFreeze = (/**
* @param {?} o
* @return {?}
*/
(o) => {
Object.freeze(o);
/** @type {?} */
const oIsFunction = typeof o === 'function';
/** @type {?} */
const hasOwnProp = Object.prototype.hasOwnProperty;
Object.getOwnPropertyNames(o).forEach((/**
* @param {?} prop
* @return {?}
*/
function (prop) {
if (hasOwnProp.call(o, prop) &&
(oIsFunction ? prop !== 'caller' && prop !== 'callee' && prop !== 'arguments' : true) &&
o[prop] !== null &&
(typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
!Object.isFrozen(o[prop])) {
deepFreeze(o[prop]);
}
}));
return o;
});
不够聪明,无法理解这里发生的事情。这是修补状态的简单尝试。状态模型如下:-
export class AuthStateModel {
isLoggedIn: Boolean;
currentUser: Object;
username: String;
}
export const defaultAuthState: AuthStateModel = {
isLoggedIn: false,
currentUser: {},
username: '',
};
我能做些什么来让它正常工作吗?
有时当我 运行 遇到这样的问题时,我无法更改对象,我只是克隆它。我通常为此使用 lodash 的 cloneDeep:
patchState({
currentUser: _.cloneDeep(currentUser),
isLoggedIn,
username,
});
此外,请尽量使您的状态可序列化。不熟悉 AWS Cognito 和 Amplify,但如果 currentUser 是一个对象,该对象具有稍后需要的方法和其他绑定到它的成员,那么我不会将 currentUser 对象存储在状态中。