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

Option to not stop watch when component is unmounted #1532

Closed
vmihailenco opened this issue Jul 7, 2020 · 9 comments
Closed

Option to not stop watch when component is unmounted #1532

vmihailenco opened this issue Jul 7, 2020 · 9 comments
Labels
✨ feature request New feature or request

Comments

@vmihailenco
Copy link

vmihailenco commented Jul 7, 2020

What problem does this feature solve?

I have a composition function that is shared between multiple components:

// global shared reactive state
let foo

function useFoo() {
  if (!foo) { // lazy initialization
      foo = ref()
      watch(foo, ...) // <- this is stopped when component that created it is unmounted
      // make some http calls etc
  }
  return foo
}

component1 = {
    setup() {
        useFoo() // lazily initialize
    }
}

component2 = {
    setup() {
        useFoo() // lazily initialize
    }
}

The problem is that watch is stopped when the component that called useFoo first is unmounted.

What does the proposed API look like?

An option for watch

watch(..., {instanceBound: false})

Or a helper that nulls the current instance:

function withNullInstance(cb: Function) {
    const old = getCurrentInstance()
    setCurrentInstance(null)
    cb()
    setCurrentInstance(old)
}

function useFoo() {
    if (!foo) {
        withNullInstance(initFoo)
    }
    return foo
}

Or export getCurrentInstance and setCurrentInstance so this can be solved in user space.

@posva
Copy link
Member

posva commented Jul 7, 2020

I think some mechanism for this would be useful for Vuex as well

@yyx990803
Copy link
Member

So in this case, when do you expect it to be stopped? It seems you will need to manually implement a reference count in order to prevent the watcher from running indefinitely (and potentially lead to memory leaks)

@yyx990803 yyx990803 added the ✨ feature request New feature or request label Jul 7, 2020
@vmihailenco
Copy link
Author

So in this case, when do you expect it to be stopped?

Not stopped at all by Vue. The data is essentially global and lives forever. I could run useFoo from the root component App.vue to achieve the same but:

  • no lazy loading which is nice if the function loads some data using HTTP
  • inconvenient if there are lots of such functions

@jods4
Copy link
Contributor

jods4 commented Jul 7, 2020

Watch, watchEffect and computed from vue are wrappers around the lower-level primitives computed and effect exported by the reactivity package.

You can import those to create watches that stop whenever you want.

@CyberAP
Copy link
Contributor

CyberAP commented Jul 7, 2020

Converting this into a higher-order function with effect (as proposed above) could potentially solve the problem:

export const createEffectComposable = (ref = ref(null)) => {
  const _effect = effect(() => {
    // ...
  })
  const _stop = () => stop(effect)
  return () => { ref, stop: _stop }
}
export const useFoo = createEffectComposable()
comp1 = {
  setup() {
    const { ref, stop } = useFoo();
  }
}

comp2 = {
  setup() {
    const { ref, stop } = useFoo();
  }
}

@vmihailenco
Copy link
Author

vmihailenco commented Jul 21, 2020

composition-api has a solution for this under name activateCurrentInstance https://github.com/vuejs/composition-api/blob/01524a4e4114cbb9443b6d697acb4cfa39f27700/src/utils/instance.ts#L101-L119 . It is private and only changes current instance in composition-api, but the idea is the same.

are wrappers around the lower-level primitives

watch is 300+ lines "wrapper" which is a little bit too much for this task.

@jods4
Copy link
Contributor

jods4 commented Jul 21, 2020

@vmihailenco It does a lot of things.
effect from reactivity is basically watchEffect.

@antfu
Copy link
Member

antfu commented Oct 1, 2020

RFC #212 provides a solution for this.

@HcySunYang
Copy link
Member

Closed, track this in vuejs/rfcs#212

@github-actions github-actions bot locked and limited conversation to collaborators Oct 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
✨ feature request New feature or request
Projects
None yet
7 participants