Angel S. Moreno
Angel S. Moreno

Reputation: 3961

Why does Mobx claim I am trying to change an observable value?

Every time I try to access the computed value of a mobx class instance, I get

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

I created a class like so:

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();

This seems to only happen when i call voiceSettings.speakers.

Update My mistake. Was tripped by the error message. I was calling the method voice. getAvailableVoices() somewhere else in my code

Upvotes: 2

Views: 2086

Answers (1)

Tholle
Tholle

Reputation: 112787

The issue is that only synchronous changes to observable data works in actions, so when Speech.getAvailableVoicesAsync() has resolved and is assigned to this.voices it's technically not inside an action anymore.

How to create asynchronous actions is discussed in the documentation. One way of going about it is to use runInAction:

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

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

    return this.voices;
}

Upvotes: 3

Related Questions