MobX: Since strict-mode is enabled, changing (observed) observable values without using an action is not allowed

15,802

Your login function is async and you need to use runInAction inside, or handle result in a separate action, or use some other way of handling async actions:

import { runInAction, makeAutoObservable } from "mobx"

class AuthStoreClass {
    authUser = null

    constructor() {
        makeAutoObservable(this)
    }

    login = async (params) => {
        const { data: { data: authUser } } = await loginUser(params)
        
        runInAction(() => {
          this.authUser = authUser
        })
        // or do it in separate function
        this.setUser(authUser)
    }

    // This method will be wrapped into `action` automatically by `makeAutoObservable`
    setUser = (user) => {
        this.authUser = authUser
    }
}

More about async actions (you can even use generators!): https://mobx.js.org/actions.html#asynchronous-actions

In MobX version 6 actions are enforced by default but you can disable warnings with configure method:

import { configure } from "mobx"

configure({
    enforceActions: "never",
})

But be careful with doing it though, the goal of enforceActions is that you don't forget to wrap event handlers and all mutations in an action. Not doing it might cause extra re-runs of your observers. For example, if you changing two values inside some handler without action then your component might re-render twice instead of once. makeAutoObservable wraps all methods automatically but you still need to handle async methods and Promises manually.

Share:
15,802

Related videos on Youtube

mleister
Author by

mleister

Hello! My name is michael and i am currently studying at the University of Applied Sciences Upper Austria.

Updated on June 04, 2022

Comments

  • mleister
    mleister almost 2 years

    My context looks like this:

    class AuthStoreClass {
        authUser = null
    
        constructor() {
            makeAutoObservable(this)
        }
    
        login = async (params) => {
            const { data: { data: authUser } } = await loginUser(params)
            this.authUser = authUser
        }
    }
    
    const AuthStoreContext = React.createContext(null);
    
    export const authStoreObject = new AuthStoreClass()
    
    export const AuthStoreProvider = ({ children }: any) => {
        return <AuthStoreContext.Provider value={authStoreObject}>{children}</AuthStoreContext.Provider>;
    };
    export const useAuthStore = () => {
        return React.useContext(AuthStoreContext);
    };
    

    And I am using the context somewhere else in a component:

    const LoginPage = observer(() => {
        const authStore = useAuthStore()
        ...
        authStore.login(...)
    

    The last line reports the following warning:

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

    Everything works as expected. How can I fix this issue?

  • mleister
    mleister over 3 years
    Great explanation! Thank you!