Vyhledávání na webu

javascript - TypeError: Nelze přiřadit hodnotu pouze pro čtení vlastnosti '0' objektu '[object Array]' v TypeScriptu


Pracuji na Angular 8.

  1. Mám stránku, která zobrazuje tabulku. Tabulka zobrazuje data z pole objektů taskList, které komponenta získává jako @Input().
  2. Mám funkci třídění na sloupcích této tabulky.
  3. Také mám na každém řádku možnost smazání. Když kliknu na možnost smazání, provede se volání API k odstranění řádku a potom další volání k načtení pole tasklist. Toto má za následek, že pro stejné
  @Effect()
  DeleteTask$: Observable<Action> = this.actions$.pipe(
    ofType(importActions.DELETE_TASK),
    switchMap(params =>
      this.globalService
        .deleteTask(params)
        .mergeMap(deleteSuccess => {
          return from([
            new importActions.DeleteTaskSuccess(deleteSuccess),
            new importActions.LoadTaskList(),
          ]);
        })
        .catch((error, caught) => {
          return Observable.of(new GlobalError(error));
        }),
    ),
  );

Můj problém je v tom, že funkce řazení funguje dobře při prvním načtení stránky. Ale pokud smažu řádek a pak načtu seznam úkolů po smazání, dostanu následující chybu:

ERROR Error: Uncaught (in promise): TypeError: Cannot assign to read only property '0' of object '[object Array]'
TypeError: Cannot assign to read only property '0' of object '[object Array]'

Podle chybové zprávy následující funkce v mém kódu způsobuje chybu

  exchange(a, b) {
    const temp = this.taskList[a];
    this.taskList[a] = this.taskList[b]; //this line gives error
    this.taskList[b] = temp;
  }

Tato funkce je součástí třídicího kódu, který používá pole tasklist a třídí ho.
Průběh je ngOnchanges(detekuje změnu v poli taskList) volá --> this.taskChange('export_name', 'asc') na základě nějaké podmínky volá --> this.exchange(a, b)

Následuje moje metoda ngOnChanges

ngOnChanges(changes: SimpleChanges) {
    if (this.taskList !== null && this.taskList !== undefined) {
      this.taskChange('export_name', 'asc');
    }
  }

Následující je hlavní metoda třídění

  async taskChange(value, taskOrder) {
    this.sortOrder = taskOrder;
    this.selectedValue = value;
    const expr = {
      asc: (a, b) => a > b,
      desc: (a, b) => a < b,
    };
    for (let i = 0; i < this.taskList.length; i++) {
      for (let j = i + 1; j < this.taskList.length; j++) {
        switch (value) {
          case 'export_name':
            if (
              expr[this.sortOrder](this.taskList[i].name, this.taskList[j].name)
            ) {
              this.exchange(i, j);
            }
            break;
          case 'file_type':
            let type1;
            let type2;
            type1 = this.exportType.transform(this.taskList[i].code, []);
            type2 = this.exportType.transform(this.taskList[j].code, []);
            if (expr[this.sortOrder](type1, type2)) {
              this.exchange(i, j);
            }
            break;
        }
      }
    }
  }

Nejsem si jistý, co přesně způsobuje tuto chybu, když se pole změní podruhé. Zkoušel jsem spoustu věcí, ale žádná z nich nefungovala. Z toho, co jsem našel online, se to může dít proto, že se snažím měnit pole, které jsem obdržel jako @Input. Ale výše uvedený kód, který mění pole 'tasklist', funguje při prvním načtení stránky. Přestane fungovat až poté, co se pole změní. Mohl by mi někdo pomoci?

Odpověď č. 1

Zkuste vytvořit kopii pole před tím, než se jej pokusíte seřadit. Například pomocí operátoru rozbalení.

arrayForSort = [...this.taskList]

Poté po seřazení byste jej mohli přiřadit zpět do pole taskList

Odpověď č. 2

Pro ty, kteří se k tomuto problému dostanou s touto chybovou zprávou při používání React/Redux, může být problém v tom, že se pokoušíte přímo měnit stav, což není povoleno.

V mém případě jsem měl tuto konfiguraci pro získání stavu uvnitř thunk (zjednodušeně):

import store from "./myStore";

const state = store.getState();
const getItems = state => state.user.items;
const items = getItems(state);
// ↓ this blew up as it was attempting to manipulate `state`
items.sort((a, b) => a.order - b.order);

To pro mě opravila:

import store from "./myStore";

const state = store.getState();
const getItems = state => state.user.items;
// ↓ in my case items is an array, so I create a new array by spreading state here
const items = [...getItems(state)];
// ↓ which means we're not manipulating state, but just our `items` array alone
items.sort((a, b) => a.order - b.order);

Související články