Почему я получаю "TypeEror: Cannot freeze"? - PullRequest
0 голосов
/ 24 сентября 2018

Я работаю над угловым приложением, которое использует магазин и эффекты ngrx.Я получаю

«Ошибка типа: невозможно заморозить»

при отправке действия из моего компонента.Я написал это для функции загрузки файлов.Я думаю, что я мутирую государство, но не могу понять, где и как это решить.Вот мой подробный код:

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;
        }
    }
}

1 Ответ

0 голосов
/ 01 ноября 2018

Похоже, вы используете пакет 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));
}

Если кто-то еще знает какие-либо потенциальные недостатки этого подхода, я был бы признателен за ваш вклад.

...