简体   繁体   中英

Mobx changing observable values outside of action

I'm getting the following error:

proxyConsole.js:54 Error: [mobx] Invariant failed: Since strict-mode is enabled, changing observed observable values outside actions is not allowed. Please wrap the code in an `action` if this change is intended. Tried to modify: ObservableObject@1.items
    at invariant (mobx.module.js:2326)
    at fail (mobx.module.js:2321)
    at checkIfStateModificationsAreAllowed (mobx.module.js:2890)
    at ObservableValue../node_modules/mobx/lib/mobx.module.js.ObservableValue.prepareNewValue (mobx.module.js:796)
    at setPropertyValue (mobx.module.js:1673)
    at Object.set [as items] (mobx.module.js:1641)
    at Store.js:41
    at <anonymous>

But I am wrapping the function in an action so I'm a little confused:

import { observable, useStrict, action } from 'mobx';
import Services from './Services';

// ...

getAllTodos: action(() => {

    Services.getAllTodos()
    .then((response) => {

        state.items = response.data;

    }).catch((error) => {
        console.error(error);
    });

}),

Services.js

// ...

getAllTodos () {
    return axios.get(root + '/items/');
}

What am I missing here?

A function that alters the observables needs to be wrapped in action , so use it on the callback as well:

getAllTodos: action(() => {

  Services.getAllTodos()
  .then(action((response) => {
    state.items.replace(response.data);
  })).catch((error) => {
    console.error(error);
  });
})

As stated in the MobX docs here :

The action wrapper / decorator only affects the currently running function, not functions that are scheduled (but not invoked) by the current function! This means that if you have a setTimeout, promise.then or async construction, and in that callback some more state is changed, those callbacks should be wrapped in action as well!

Thus, you'd have to wrap the scheduled promise.then here in an action as well, apart from the parent function. (Note that you'd only be able to use the @action on the class-level function)

There are two ways of doing it:

action(
  asyncFunction().then(
    action((args) => {
      // Your function body here
    })
  )
)

--or--

Use the @action.bound :

@action
asyncFunction().then(
  yourStateModifyingFunction();
)

@action.bound
yourStateModifyingFunction() {
  // Your function body here
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM