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

feat(untracked): enable disabling tracking temporarily #1130

Closed
wants to merge 2 commits into from
Closed

feat(untracked): enable disabling tracking temporarily #1130

wants to merge 2 commits into from

Conversation

basvanmeurs
Copy link
Contributor

@basvanmeurs basvanmeurs commented May 6, 2020

In computed or watchEffect functions, it may be convenient to get a value of a ref without actually tracking it:

const scrollOffsetX = computed(() => {
  return scrollX.value /* I do not want to track this */ - additionalBounds.sx /* reactive, should be tracked */;
});

The same can be achieved by explicitly defining which refs should be tracked in a watch(). This works find for me but I thought that this small utility function can be handy when you'd simply want to exclude tracking for one specific ref.

Proposed change in this PR:

const scrollOffsetX = computed(() => {
  let scrollXValue = 0;
  untracked(() => scrollXValue = scrollX.value);
  return scrollXValue - additionalBounds.sx;
});

Alternatively we could export pauseTracking and resetTracking but that's a bit more dangerous. The untracked method protects the user against not resetting tracking.

@yyx990803
Copy link
Member

What is the reason to avoid tracking here? Is it solely for performance?

@basvanmeurs
Copy link
Contributor Author

What is the reason to avoid tracking here? Is it solely for performance?

Not performance. In my use case I want to sync a scrollbar. I needed to get the current scroll value without tracking it to avoid recursive feedback while scrolling.

Possibly it's an edge case.

@yyx990803
Copy link
Member

In general I am against use cases like this since the whole point of reactivity is having a consistent state graph and this API is like intentionally giving the user a tool to make the graph inconsistent. I can't help but feel that it's a sign that you need to rethink how you are approaching the problem. There are probably better ways to achieve your goal without introducing an API for it.

@yyx990803 yyx990803 closed this Jun 25, 2020
@ryansolid
Copy link

ryansolid commented Aug 17, 2020

The best use of something like untracked is to safeguard against people unknowingly doing stupid things in terms of execution when they are consumers of an API.

I've hit a number oftimes is you are making some composable hook-like behaviour that takes a callback function.. like say some sort of reactive mapping where you want to update on list change. While arguably more of a performance consideration sometimes the expected behaviour is directionally downward and someone accessing reactive variables actually can raise havoc in the owning context.

Like, the setup function is inert so the worse thing that happens when someone accesses a reactive variable out of context is it's not reactive, it doesn't update. Sometimes you need to create a similar inert zone under an existing tracking context. Without it, it is very easy to create scenarios where you are just causing upstream tracking in those cases causing crazy (often initially unnoticed) performance degradation.

Not performance. In my use case I want to sync a scrollbar. I needed to get the current scroll value without tracking it to avoid recursive feedback while scrolling.

These cases are more common than you'd think. While most of the time something like an event handler firing outside of reactive context will not be tracking and you won't hit this, there are plenty of times that you are watching refA to run a reducing operation on refB. You need to access refB to get the next value but you should never track refB. The graph isn't getting out of sync as it's self-referencing.

There are tons of cases like this once you try to do anything more complicated. The underlying library has this ability since it's essential to model certain types of behaviours. It's fine not to put it in end userland initially. But I'll be surprised if this decision is not revisited.

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

Successfully merging this pull request may close these issues.

None yet

3 participants