Reputation: 51638
Say I have an object with two MobX @observable
fields:
class Address {
@observable country
@observable city
}
When one of them changes, I want to call a function that changes the other one. For example, when country
changes, I might want to clear city
if its value isn't valid for the new country.
Is there a good pattern for this?
I don't think I can use autorun
. Since I'm trying to change an observable value, and I have enforceActions
turned on, I need to change it in an action
. But this throws an error "Autorun does not accept actions since actions are untrackable":
autorun(action(() => {
if (this.country === 'US' && this.city === 'Paris') this.city = '';
}));
I know I can add a @computed
function that returns either city
or a new value. But then the original value of city
is still there, and will get returned when country
changes back. I don't want this; I want to permanently change city
.
@computed get realCity() {
if (this.country === 'US' && this.city === 'Paris') return '';
return this.city;
}
Upvotes: 4
Views: 7902
Reputation: 5391
observe(state, "country", ({ oldValue, newValue }) => this.handleCountryChange(oldValue, newValue));
handleCountryChange = (oldValue, newValue) => {}
Upvotes: 0
Reputation: 112777
You could use observe to observe the object in the constructor, and reset the city if the country changed.
Example (JSBin)
class Address {
@observable country = 'Sweden';
@observable city = 'Stockholm';
constructor() {
observe(this, (change) => {
if (change.name === 'country') {
// Put your logic for changing the city here
this.city = '';
}
});
}
}
const address = new Address();
console.log(`${address.country}, ${address.city}`);
address.country = 'Spain';
console.log(`${address.country}, ${address.city}`);
Upvotes: 4
Reputation: 5442
I think you should look at your problem with a different angle.
The thing I am asking myself is: isn't there something you could do to avoid the problem you face altogether?
Why allow the situation to happen in the first place?
Regarding mobx specific patterns this bit of docs is useful:
As a rule of thumb: use autorun if you have a function that should run automatically but that doesn't result in a new value. Use computed for everything else. Autoruns are about initiating effects, not about producing new values. Mobx docs
Upvotes: 2
Reputation: 994
This task can be done via the "when" process initialized in the store constructor:
class store(){
constructor(){
when (){
()=>{(this.country === 'US' && this.city === 'Paris')}
()=>{ this.city = ''}
}
}
}
A full and well documented explanation can be found here: https://mobx.js.org/refguide/when.html
Upvotes: 1