question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to create a setter for an observable prop

See original GitHub issue

I noticed a repeated pattern in my code setup, usually in my store i would have some observables defined as follows:

@observable loading: boolean = true;
@observable name: string = '';
// ..

And then for each observable, i would create a matching setter action:

@action setLoading = (value: boolean) => {
  this.loading = value;
};

@action setName = (value: string) => {
  this.name = value;
};

// ..

Later on in my components that have the store injected in them, i can easily access this.props.store.name and this.props.store.setName('foo').

This is not an issue when you have few observables, but for a large store with tens of observables, this becomes a tedious process and could lead to having errors when we wish to modify that pice of code, say the name of the observable for example. mobx should automate this for us i thought to my self, and indeed i found out about observable.box, although it requirers using .get() to retrieve the value of the observable, it would’ve been more convenient to have .get() automatically returned if .set() is not called.

A perfect api would be something like this:

loading: boolean = observable(true);
// or with decorators (more convenient)
@observable loading: boolean = true;
// or if it cannot be implemented directly for some reason
@observable @box loading: boolean = true;
// or just @box
@box loading: boolean = true;

// usage
console.log(this.props.store.loading); // prints true
this.props.store.loading.set(false);
console.log(this.props.store.loading); // prints false

Can this be done currently with mobx? did i miss something in the docs? if not, any thoughts on implementing something like this?

Coming back to react native, i’ve tried using boxed values:

test: string = observable('foo');
// also tried
test: string = observable.box('foo');

console.log(this.props.store.test);
this.props.store.test.set('voila!');
console.log(this.props.store.test);
// also tried console.log(this.props.store.test.get());

An error is being thrown in all cases: simulator screen shot feb 17 2017 2 05 18 am

Please advise on this, thanks.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:70 (18 by maintainers)

github_iconTop GitHub Comments

8reactions
sonayecommented, Feb 23, 2017

@mweststrate I create setters because they are needed to mutate observables, aren’t they? how else would I update the value, or in the first place why would one create an observable if it was not changing? I don’t mutate the data directly outside the store like this this.observable = 'bar';, instead i wrap it in a function/setter/action to ensure consistency across the app.

I understand that piece of code you provided, it’s now clear to me that i misused the api (maybe we can polish the docs on that a little) and it’s perhaps not rn related. What I am proposing is that by default mobx would define the setter attached to the observable as set x (v) { this._x = v }, and unless it was overwritten by a custom logic as you pointed out, this would be the default behavior. This saves us the headache of writing some repeated boilerplate. mobx is is all about automating things for us, and it’s already doing an excellent job, i think this minor update would make a significant impact. Just by having this I would delete +250 lines of code of an application that I am working on as we speak.

I am proposing that just by writing one line @observable hello = 'world!'; you can directly read the value from the store store.hello and set it store.hello.set('new world!');

Instead of:

@observable private _hello  = 'world!';

get hello ()  {
  return this._hello;
}

set hello(value) {
  this._hello = value
}

get() is already automated, set() is not. What is your view on adding this? https://github.com/mobxjs/mobx/issues/69 could be related.

5reactions
hccamposcommented, Feb 23, 2017

I think this proposal completely defeats the purpose of strict mode and @action. Actions should represent exactly that: actions that the user performs and that should be traceable in the dev tools, etc. Having a simple way to just set values directly goes against this. If you have an action to set a single property, it should be marked and easily identifiable, just like any other action that is more complex.

To give you guys an example, in our codebase we make sure we don’t even have any actions in our models. The models define the data we store and can contain methods to modify that data, but they contain no actions at all. All the actions go in services/stores that are called by the view. And they should have as little granularity as possible. When something goes wrong, we only have a few places that we need check in the services/stores to find the problem. If you try to modify the state directly MobX will throw.

Basically you get a nice one-way flux where your view renders the state, and then calls actions in the stores/services to update the state instead of modifying the state directly. This is similar to Redux but in a mutable way and without all the boilerplate: instead of an immutable state tree, action types, and action creators and all that, you call action methods that mutate the state and MobX takes care of the rest.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Make setter an action using Mobx makeObservable in ...
In mobx if I want to use interheritance I need to use makeObservable rather than makeAutoObservable. But using makeObservable requires I ...
Read more >
How to proxy JavaScript observable with getters and setters
How to proxy JavaScript observable with getters and setters ... Copy `data` to separate property, so that `data` ... Custom getter/setter for `data`...
Read more >
Using Getters and Setters in TypeScript and Angular
Getters and setters are a well known pattern that is used in different languages. In this article, I want to help you to...
Read more >
Trouble with observableObject getter + setter and special ...
Hello Daniel, Internally we create function getters and setters for the properties of the observable object using the Function constructor.
Read more >
Creating observable state - MobX
Properties, entire objects, arrays, Maps and Sets can all be made observable. The basics of making objects observable is specifying an annotation per ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found