Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to track object mutations? #662

Closed
tkrotoff opened this issue Nov 17, 2016 · 11 comments
Closed

How to track object mutations? #662

tkrotoff opened this issue Nov 17, 2016 · 11 comments

Comments

@tkrotoff
Copy link

tkrotoff commented Nov 17, 2016

Example with Moment.js:

var person = mobx.observable({
  birthday: moment()
});

mobx.autorun(function() {
  console.log('autorun: ' + person.birthday.toString());
});

person.birthday = moment(person.birthday).add(1, 'day'); // Ugly but works
person.birthday.add(1, 'day'); // Does not work

console.log('no autorun: ' + person.birthday.toString());

Output:

autorun: Thu Nov 17 2016
autorun: Fri Nov 18 2016
no autorun: Sat Nov 19 2016

Online jsFiddle: https://jsfiddle.net/tkrotoff/ek64vvtf/

autorun is not being called when running person.birthday.add(1, 'day').
Moment.add mutates birthday and Mobx does not know about it.

How can it be done elegantly?

PS: I've spent a long time in my code base before understanding why it did not work as I expected, I suggest to document this to avoid others the same mistake

@mattruby
Copy link
Member

Check out my timer examples, https://github.com/mobxjs/mobx-examples . They
were using moment at one time. You'll want to use a computed to show the
date output. It should trigger as you'd like.

On Nov 17, 2016 4:39 PM, "Tanguy Krotoff" notifications@github.com wrote:

Example with Moment.js:

var person = mobx.observable({
birthday: moment()
});
mobx.autorun(function() {
console.log('autorun: ' + person.birthday.toString());
});
person.birthday = moment(person.birthday).add(1, 'day'); // Ugly but worksperson.birthday.add('1', 'day'); // Does not work
console.log('no autorun: ' + person.birthday.toString());

Output:

autorun: Thu Nov 17 2016
autorun: Fri Nov 18 2016
no autorun: Sat Nov 19 2016

Online jsFiddle: https://jsfiddle.net/tkrotoff/ek64vvtf/

autorun is not being called when using person.birthday.add('1', 'week').
Moment.add http://momentjs.com/docs/#/manipulating/add/ mutates birthday
and Mobx does not know about it.

How can it be done elegantly?


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#662, or mute the thread
https://github.com/notifications/unsubscribe-auth/AAIrcj9svjmypNDHZB4D3RtH9rtLNJVvks5q_NdVgaJpZM4K15jw
.

@hellectronic
Copy link
Contributor

hellectronic commented Nov 18, 2016

@tkrotoff, do you mean documenting how mobx reacts?

@tkrotoff
Copy link
Author

@mattruby
From the timer example, first initialisation: startTime: null then later startTime = moment().
Since MobX tracks property access, not values it works.

In other words (tell if wrong), Mobx tracks the pointer value (pointer as in C/C++ pointer).

That's why person.birthday.add(1, 'day') does not work: changing the value, not the pointer.
And person.birthday = moment(person.birthday).add(1, 'day') works: changing the pointer.

@nighca
Copy link

nighca commented Nov 22, 2016

@tkrotoff Actually it's Date who basically causes this confusion. Moment.js uses Date instance to store the exact value, while mobx doesn't track change of Date instance - which is difficult.

You can try this example and you'll find that mobx tries to make object content observable recursively: https://jsfiddle.net/nbk3peoa/

@nighca
Copy link

nighca commented Nov 22, 2016

@mweststrate Maybe mobx can do some monkey patch stuff to make Date instance changes trackable? Just like what mobx did with Array instances.

@kpennell
Copy link

kpennell commented Apr 9, 2017

@tkrotoff What ended up being the elegant solution to this? Tearing my hair out a bit...

@francesco-carrella
Copy link

I'm curious about that too because I have the same problem. Is there some more elegant solution?
Thanks

@tkrotoff
Copy link
Author

tkrotoff commented Apr 28, 2017

btw, will ES6 Proxy be able to solve this problem?

@mweststrate
Copy link
Member

@kpennell @francesco-carrella I recommend to treat the date as immutable, and every time you want to modify it, produce a new data and store that in a observable.ref

@francesco-carrella
Copy link

Thanks for the support @mweststrate, I ended using this way out.

@tkrotoff
Copy link
Author

tkrotoff commented Jul 3, 2018

Replying to my question "will ES6 Proxy solve this problem?", the answer is no. See https://codepen.io/tkrotoff/pen/WyWOZP

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants