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

Consider debouncing setter of Ref returned from useDebounce #407

Closed
cypressious opened this issue Mar 31, 2021 · 2 comments · Fixed by #435
Closed

Consider debouncing setter of Ref returned from useDebounce #407

cypressious opened this issue Mar 31, 2021 · 2 comments · Fixed by #435

Comments

@cypressious
Copy link

I was playing around with useDebounce and wrote the following component

<template>
  <input v-model="query">
</template>

<script lang="ts">
import { defineComponent, ref, watchEffect } from "vue";
import { useDebounce } from "@vueuse/core";

export default defineComponent({
  name: "CompositionApiComponent",
  setup() {
    const query = useDebounce(ref(''), 500)
    watchEffect(() => console.log(query.value))

    return {
      query
    }
  }
})
</script>

To my surprise, everytime I typed a letter, the watchEffect triggered and printed the value of query. What I expected to happen was that the console.log was debounced and only after I didn't type anything for 500ms, the current value will be printed.

I went to read the source of useDebounce and discovered that the setter of the returned Ref isn't actually debounced. Instead, only changes to the original Ref are reflected debouncedly. What I needed to write was

const query = ref('')
const queryDebounced = useDebounce(query, 500)
watchEffect(() => console.log(queryDebounced.value))

which seems a bit verbose. So I modified my code to the following which did what I wanted

const _query = ref('')
const query = computed({
  get: () => _query.value,
  set: useDebounceFn(v => _query.value = v, 500)
})

My proposal is to modify useDebounce so that setting values on the debounced Ref are also debounced.

@cypressious
Copy link
Author

cypressious commented Mar 31, 2021

Thinking a bit more about the issue, a couple of questions popped up.

In the current form, writes to the debounced Ref are not reflected back to the original Ref. Is this intended? If not, maybe useDebounce should return a Readonly<Ref<T>>?

In that case a new function similar to my last code snippet would make sense that doesn't take a Ref as an argument and returns a mutable Ref where changes are debounced.

Alternatively, it could be decided that writes to a Ref returned by useDebounce are allowed and are reflected back to the original Ref. However, this could be a breaking change for clients that rely on the current behavior.

@antfu
Copy link
Member

antfu commented Mar 31, 2021

useDebounce should return a Readonly<Ref>

Yeah, that was expected. At the time it was written, Vue 2 does not support the readonly API, but it does now. Thank you for spotting this and if you want, I'd be appreciated for a PR.

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

Successfully merging a pull request may close this issue.

3 participants