微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

无法使用 NGXS 修补带有更新到商店的状态我一直看到类型错误:无法冻结

如何解决无法使用 NGXS 修补带有更新到商店的状态我一直看到类型错误:无法冻结

我正在使用一个基本的 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 对象存储在 state 中。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。