Angular - "TypeError: Cannot freeze" when dispatching an action
Angular - "TypeError: Cannot freeze" when dispatching an action
我正在开发一个使用 ngrx store & effects 的 angular 应用程序。我得到
"TypeError: Cannot freeze"
从我的组件分派操作时出错。我写它是为了文件上传功能。我认为我正在改变状态,但无法弄清楚在哪里以及如何解决它。
这是我的详细代码:
Actions:
export enum FileUploadActionTypes {
UploadFile = '[File Upload] Upload File',
UploadFileSuccess = '[File Upload] Upload File Success',
UploadFileFailure = '[File Upload] Upload File Failure'
}
export class UploadFile implements Action {
readonly type = FileUploadActionTypes.UploadFile;
constructor(public payload: any) {}
}
export class UploadFileSuccess implements Action {
readonly type = FileUploadActionTypes.UploadFileSuccess;
constructor(public payload: any) {}
}
export class UploadFileFailure implements Action {
readonly type = FileUploadActionTypes.UploadFileFailure;
constructor(public payload: any) {}
}
export type FileUploadActionsUnion = UploadFile | UploadFileSuccess | UploadFileFailure;
Service:
export class FileUploadService {
constructor(private httpClient: HttpClient) {
}
uploadFile(file: any): Observable<any> {
return this.httpClient.post<any[]>('/api-url/', file);
}
}
Effect:
@Effect()
uploadFile$ = this.actions$.pipe(
ofType<UploadFile>(FileUploadActionTypes.UploadFile),
mergeMap(action => this.fileUploadService.uploadFile(action.payload).pipe(
map(result => new UploadFileSuccess(result)),
catchError(error => of(new UploadFileFailure(error)))
))
)
Reducer:
export interface State {
fileUploadSuccessResponse: any,
fileUploadFailureResponse: any
}
export const initialState = {
fileUploadSuccessResponse: null,
fileUploadFailureResponse: null
}
export const getFileUploadSuccessResponse = state => state.fileUploadSuccessResponse;
export const getFileUploadFailureResponse = state => state.fileUploadFailureResponse;
export function reducer(state: State = initialState, action: FileUploadActionsUnion):State {
switch(action.type) {
case FileUploadActionTypes.UploadFile: {
return {
...state
}
}
case FileUploadActionTypes.UploadFileSuccess: {
return {
...state,
fileUploadSuccessResponse: action.payload
}
}
case FileUploadActionTypes.UploadFileFailure: {
return {
...state,
fileUploadFailureResponse: action.payload
}
}
default: {
return state;
}
}
}
看来您正在使用 ngrx-store-freeze
npm 包。这个包确保你对商店所做的任何更新都不会直接改变。此过程的一部分是将 Object.freeze()
应用于您尝试分派的操作的 payload
对象。即 this.store.dispatch(new UploadFiles(file))
.
<input type="file">
控件的默认行为是将其值保存为 FileList
对象。因为此对象是原始数据类型,Javascript 会将其视为只读,从而防止您写入其属性。这也解释了为什么 Object.freeze()
失败,因为它无法将冻结应用于只读数据类型。
我最近在使用 NGRX 和 <input type="file">
表单控件时遇到了同样的问题。解决方法是在发送到商店之前将 FileList
克隆到一个新对象中。
onChange(control: FormControl) {
const primitiveFileList: FileList = control.value;
const clonedFiles = { ...primitiveFileList };
this.store.dispatch(new UploadFiles(clonedFiles));
}
如果其他人知道这种方法有任何潜在的缺点,我将不胜感激。
我正在开发一个使用 ngrx store & effects 的 angular 应用程序。我得到
"TypeError: Cannot freeze"
从我的组件分派操作时出错。我写它是为了文件上传功能。我认为我正在改变状态,但无法弄清楚在哪里以及如何解决它。 这是我的详细代码:
Actions:
export enum FileUploadActionTypes {
UploadFile = '[File Upload] Upload File',
UploadFileSuccess = '[File Upload] Upload File Success',
UploadFileFailure = '[File Upload] Upload File Failure'
}
export class UploadFile implements Action {
readonly type = FileUploadActionTypes.UploadFile;
constructor(public payload: any) {}
}
export class UploadFileSuccess implements Action {
readonly type = FileUploadActionTypes.UploadFileSuccess;
constructor(public payload: any) {}
}
export class UploadFileFailure implements Action {
readonly type = FileUploadActionTypes.UploadFileFailure;
constructor(public payload: any) {}
}
export type FileUploadActionsUnion = UploadFile | UploadFileSuccess | UploadFileFailure;
Service:
export class FileUploadService {
constructor(private httpClient: HttpClient) {
}
uploadFile(file: any): Observable<any> {
return this.httpClient.post<any[]>('/api-url/', file);
}
}
Effect:
@Effect()
uploadFile$ = this.actions$.pipe(
ofType<UploadFile>(FileUploadActionTypes.UploadFile),
mergeMap(action => this.fileUploadService.uploadFile(action.payload).pipe(
map(result => new UploadFileSuccess(result)),
catchError(error => of(new UploadFileFailure(error)))
))
)
Reducer:
export interface State {
fileUploadSuccessResponse: any,
fileUploadFailureResponse: any
}
export const initialState = {
fileUploadSuccessResponse: null,
fileUploadFailureResponse: null
}
export const getFileUploadSuccessResponse = state => state.fileUploadSuccessResponse;
export const getFileUploadFailureResponse = state => state.fileUploadFailureResponse;
export function reducer(state: State = initialState, action: FileUploadActionsUnion):State {
switch(action.type) {
case FileUploadActionTypes.UploadFile: {
return {
...state
}
}
case FileUploadActionTypes.UploadFileSuccess: {
return {
...state,
fileUploadSuccessResponse: action.payload
}
}
case FileUploadActionTypes.UploadFileFailure: {
return {
...state,
fileUploadFailureResponse: action.payload
}
}
default: {
return state;
}
}
}
看来您正在使用 ngrx-store-freeze
npm 包。这个包确保你对商店所做的任何更新都不会直接改变。此过程的一部分是将 Object.freeze()
应用于您尝试分派的操作的 payload
对象。即 this.store.dispatch(new UploadFiles(file))
.
<input type="file">
控件的默认行为是将其值保存为 FileList
对象。因为此对象是原始数据类型,Javascript 会将其视为只读,从而防止您写入其属性。这也解释了为什么 Object.freeze()
失败,因为它无法将冻结应用于只读数据类型。
我最近在使用 NGRX 和 <input type="file">
表单控件时遇到了同样的问题。解决方法是在发送到商店之前将 FileList
克隆到一个新对象中。
onChange(control: FormControl) {
const primitiveFileList: FileList = control.value;
const clonedFiles = { ...primitiveFileList };
this.store.dispatch(new UploadFiles(clonedFiles));
}
如果其他人知道这种方法有任何潜在的缺点,我将不胜感激。