You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular+NgRx+Firebase登录时NgRx Store报TypeError: Cannot freeze求助

问题原因

NgRx 在开发模式下默认开启状态不可变性校验,会对所有存入 Store 的对象执行递归 Object.freeze 操作,避免状态被意外修改保证不可变性。
而 Firebase 返回的 UserCredential 不是普通纯 JavaScript 对象,它包含内置方法、访问器属性、内部循环引用等宿主对象特性,浏览器原生的 Object.freeze 无法处理这类对象,因此抛出 Cannot freeze 错误。

代码错误点

你直接将 Firebase 返回的原生 UserCredential 对象存入 NgRx Store,违反了 NgRx 要求「状态必须是可序列化的纯数据对象」的规范。你之前手动调用 Object.freeze 能临时生效,是因为 NgRx 内部的冻结逻辑检测到对象已经被冻结就会跳过深层遍历,刚好绕开了不可冻结的内部属性,属于临时规避方案,不符合规范,后续做状态持久化、时间旅行调试都会出现问题。

正确修复方案

不要直接存储完整的 UserCredential 对象,只提取业务需要的纯数据字段,组装成普通对象后再存入 Store,示例如下:

1. 调整 State 定义

// 自定义业务需要的凭证类型,不直接依赖Firebase的类型
export interface UserCredentials {
  uid: string;
  email: string | null;
  displayName: string | null;
  // 补充其他业务需要的字段
}

export interface CoreState {
  readonly credentials: UserCredentials | null;
}

export const initialCoreState: CoreState = {
  credentials: null
}

2. 调整 Effect 中的数据转换逻辑

map((userCredential: UserCredential) => {
  // 提取需要的字段,组装为纯JS对象
  const credentials = {
    uid: userCredential.user.uid,
    email: userCredential.user.email,
    displayName: userCredential.user.displayName
    // 补充其他需要的字段
  };
  return CoreActions.signInSuccess({ credentials });
})

3. 同步调整 Action 和 Reducer 的对应类型

调整完成后无需手动调用 Object.freeze,也不会再出现冻结错误,同时符合 NgRx 状态可序列化的规范。


内容的提问来源于stack exchange,提问作者user5426760

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 02:06:05