JAVASCRIPT

Vue 3 Composable for Debounced Input Handling

Optimize performance and prevent excessive function calls by implementing a reusable debounce composable in Vue 3 for input fields and other rapid events.

// composables/useDebounce.js
import { ref, watch, onUnmounted } from 'vue'

/**
 * A composable to debounce a value.
 * @param {import('vue').Ref} valueRef The ref to watch for changes.
 * @param {number} delay The debounce delay in milliseconds.
 * @returns {import('vue').Ref} A ref with the debounced value.
 */
export function useDebounce(valueRef, delay = 500) {
  const debouncedValue = ref(valueRef.value)
  let timeoutId = null

  watch(valueRef, (newValue) => {
    if (timeoutId) {
      clearTimeout(timeoutId)
    }
    timeoutId = setTimeout(() => {
      debouncedValue.value = newValue
      timeoutId = null
    }, delay)
  }, { immediate: true })

  onUnmounted(() => {
    if (timeoutId) {
      clearTimeout(timeoutId)
    }
  })

  return debouncedValue
}

// App.vue (or any component)
<script setup>
import { ref, watch } from 'vue'
import { useDebounce } from './composables/useDebounce'

const searchTerm = ref('')
const debouncedSearchTerm = useDebounce(searchTerm, 500)

// Simulate an API call
const searchResults = ref([])
async function performSearch(query) {
  if (query.trim() === '') {
    searchResults.value = []
    return
  }
  // In a real app, this would be an actual API call
  console.log(`Performing search for: "${query}"`) 
  searchResults.value = [`Result for ${query} A`, `Result for ${query} B`]
}

// Watch the debounced value to trigger the search
watch(debouncedSearchTerm, (newVal) => {
  performSearch(newVal)
}, { immediate: true })

</script>

<template>
  <div>
    <h1>Debounced Search Example</h1>
    <input
      type="text"
      v-model="searchTerm"
      placeholder="Type to search..."
      style="width: 300px; padding: 8px; font-size: 16px;" 
    />
    <p>Search Term (live): {{ searchTerm }}</p>
    <p>Search Term (debounced): {{ debouncedSearchTerm }}</p>

    <h2>Search Results:</h2>
    <ul v-if="searchResults.length">
      <li v-for="result in searchResults" :key="result">{{ result }}</li>
    </ul>
    <p v-else>No results or type to search.</p>
  </div>
</template>
How it works: This snippet provides a reusable Vue 3 composable, `useDebounce`, to delay the execution of a function or update of a reactive value until a specified amount of time has passed without any further changes. This is incredibly useful for optimizing performance in scenarios like search inputs, preventing excessive API calls on every keystroke. The composable takes a `ref` and a `delay`, returning a new `ref` whose value only updates after the `delay` has elapsed since the last change to the input `ref`. It also handles cleanup with `onUnmounted` to prevent memory leaks.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs