Почему Mobx утверждает, что я пытаюсь изменить наблюдаемое значение?

#mobx

#mobx

Вопрос:

Каждый раз, когда я пытаюсь получить доступ к вычисленному значению экземпляра класса mobx, я получаю

 [MobX] Since strict-mode is enabled, changing (observed) observable values without using an action is not allowed. Tried to modify: VoiceSettings@3.voices
 

Я создал класс следующим образом:

 import {action, computed, makeObservable, observable} from "mobx"

export default class VoiceSettings {
    @observable language: Language = 'en';
    @observable speaker?: Voice;
    @observable voices: Voice[] = [];

    constructor() {
        makeObservable(this);
        this.getAvailableVoices();
    }

    async getAvailableVoices() {
        this.voices = await Speech.getAvailableVoicesAsync();
        return this.voices;
    }

    @computed
    get speakers(): string[] {
        return this.voices
            .filter(voice => voice.language.startsWith(this.language))
            .map(voice => voice.name)
    }

    @action
    setLanguage(language: Language) {
        this.language = language;
    }
}

export const voiceSettings = new VoiceSettings();
 

Кажется, это происходит только при вызове voiceSettings.speakers .

Обновите мою ошибку. Сработало сообщение об ошибке. Я вызывал метод voice. getAvailableVoices() где-то еще в своем коде

Комментарии:

1. speakers имеет только a getter , поэтому он доступен только для чтения .

2. Понял @connexo, но, конечно, я могу сделать voiceSettings.speakers.map() это на готовом var, правильно?

Ответ №1:

Проблема в том, что в действиях работают только синхронные изменения наблюдаемых данных, поэтому, когда Speech.getAvailableVoicesAsync() они разрешены и назначены this.voices , они технически больше не находятся внутри действия.

Как создавать асинхронные действия обсуждается в документации. Один из способов сделать это — использовать runInAction :

 async getAvailableVoices() {
    const voices = await Speech.getAvailableVoicesAsync();

    runInAction(() => {
        this.voices = voices;
    });

    return this.voices;
}