Still getting confused about reactivity... Help!


#1

Okay, so I’ve created examples of both a non-working and a working version of my issue…
This is obviously a slightly contrived example, my real use-case is somewhat more complex, but, it highlights my point well enough.

Broken Version: http://meteorpad.com/pad/6e4qXnfdZvyfPKPhR/Reactivity%20with%20Autorun

Working Version: http://meteorpad.com/pad/CXXJxcWXQ9467xRY8/Reactivity%20with%20Helper

Essentially, what I expect to happen is the button press causes the score to go up by 5 points… The helper that adds the “***” is merely an example of a function that transforms the result in some way.

If the data being passed through from the parent template is reactive, then I would expect the autorun (in the broken example) to fire when it changes, but it doesn’t.

If the value isn’t reactive, I wouldn’t expect it to fire the helper in the second (working) example, but it does!

Can someone please explain what the hell is going on!?

EDIT: Someone has stated that it’s because Template.instance() is reactive and the template context isn’t… If that’s the case why doesn’t replacing the line: var score = self.data.score; with var score = Template.instance().data.score; cause the first example to start working?


#2

As an example of where I am using this sort of strategy; I have a document reference to an associated Image stored as a nested-field inside my Product document. So when viewing this Product I’d like to have the subscription to the Image autorun, update a local value and rerender the image, if the value ever changes (much like the autorun in the broken example).


#3

Lets see if I can explain this in a way that will make sense to you.

Whoever said data contexts are not reactive is completely right but a template instance is not reactive.

Basically the template instance registers a tracker dependency if the data context is set to reactive data source. It will then re-run the helpers on the template anytime the reactive source’s data changes and thus you get reactivity.

the template.autorun works in exactly the same way but needs a reactive data source inside the function to register the dependancy. In your example that’s not working, you use self.data.score which will not register a dependency to trigger the autorun once it gets invalidated. If you change this to Template.currentData().score you will get the desired result. Please note though that using auto run to set up and change a reactive var on a template isn’t really an optimal way to achieve reactivity.


#4

Ah okay, I have tried using Template.instance().data.score but that didn’t work. I assume that currentData() does something different!?


#5

Yes, it returns a reactive data source. Much like doing a Players.find({ name: "Ada Lovelace" }).fetch()[0] would not be a reactive data source, but Players.findOne({ name: "Ada Lovelace" }) would be.


#6

Okay, I had no idea about currentData() thanks for that pointer! :wink:


#7

No problem… Just in case you need some further reading :slight_smile: http://docs.meteor.com/#/full/template_currentdata