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

limitation on mutating observables in reaction #25

Open
janat08 opened this issue May 19, 2018 · 10 comments
Open

limitation on mutating observables in reaction #25

janat08 opened this issue May 19, 2018 · 10 comments

Comments

@janat08
Copy link

janat08 commented May 19, 2018

Is there a reason for why this limitation exists? I can see how this may cause loops, but otherwise there's nothing wrong with having reaction triggered in reaction (not in, after).

@solkimicreb
Copy link
Member

Hi!

Mutating observables inside reactions won't trigger other reactions, but they don't break the app in any other way. Triggering other reactions in reactions could cause infinite loops and a very obfuscated control flow. Reactions are meant to react on data changes and not to trigger other data changes. (They should save or visualize data as examples).

In the past the lib allowed triggering reactions inside reactions and automatically cut the infinite loops, but I had to remove this when I added custom schedulers. With custom async schedulers and observable mutations inside reactions it would be possible to cause async infinite loops, which is a really nasty thing.

Do you have an example use case where you would like to mutate reactive data inside reactions?

PS: I also saw the other issue, where you referenced this. I would advise you against using NX framework in serious projects. Some parts of it (like this lib and the queue-util) are actively maintained and prod ready, but the project as a whole is stuck in beta until I have more time to finish it.

@janat08
Copy link
Author

janat08 commented May 20, 2018

Mobx has autorun, and meteor has autorun(it being the only thing they have). Mobx says it's meant as a bridge to imperative code, and I suppose it's a consumer of a reaction/computed prop, so I say reactive programming that isn't responsive to itself is seriously gimped.

@solkimicreb
Copy link
Member

solkimicreb commented May 20, 2018

Mobx autorun is the equivalent of nx-observe observe, they are both meant to react on data changes not to update data (just log or persist it).

Mobx:

This is usually the case when you need to bridge from reactive to imperative code, for example for logging, persistence, or UI-updating code.

nx-observe:

Reactions are meant to react on data changes and not to trigger other data changes. (They should save or visualize data as examples).

MobX autorun also throws (or warns) if you mutate observables inside it. Overdoing transparent reactivity is a hell. You will quickly loose which function triggers which ones. This is why you can't call setState in React renders or can't mutate observables in MobX or nx-observe reactions.

Do you have a use case (code snippet) where you would like to update reactive data in reactions?

EDIT: the MobX docs is a bit poorly worded here. autorun is a bridge from imperative to reactive programming, not the other way around. computed is a bridge inside reactive programming, the nx-observe equivalent is vanilla ES5 getters. Perhaps this is what you are looking for, check the computed props example in this docs section.

@janat08
Copy link
Author

janat08 commented May 21, 2018

Might actually work.

@janat08
Copy link
Author

janat08 commented May 21, 2018

Anyway it feels a little weird to me. I'll give it a try, but here's meteor's guide to tracker: https://github.com/meteor/docs/blob/version-NEXT/long-form/tracker-manual.md, obviously it's somewhat slower.

@janat08
Copy link
Author

janat08 commented May 21, 2018

I'm trying to map observer api onto tracker api.

@janat08
Copy link
Author

janat08 commented May 21, 2018

Im looking to pass invariable amount of functions into getter for Dependency since it supports multiple calls on changed method, and actually be able to tell what function called the method in production.

@solkimicreb
Copy link
Member

solkimicreb commented May 22, 2018

I feel like I can't help here, what's is your overall goal? Would you like to track which function uses which observable values?

In that case I suggest you to check the experimental debugger option. It is documented here and the simplest use looks like this:

observe(fn, {
  debugger: console.log
})

debugger expects a function, which receives a context object about the triggering mutations and reactive wiring. Passing console.log is the simplest way to use it, but you can write your own aggregating debugger if needed.

I don't know if this is what you are looking for.

@janat08
Copy link
Author

janat08 commented May 22, 2018

Convert meteor's reactive lib tracker to yours, im trying to do.

@janat08
Copy link
Author

janat08 commented May 22, 2018

Ur typical implementation for observable would be call new Dependency(), and then dependency.changed() when it was change in function, and dependency.depend() when the observable was used. I was thinking I should change dependency.changed( ) whould set observable on function where it was used as getter for dependency, but Im not sure that will work.

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

2 participants