79329336

Date: 2025-01-04 18:04:33
Score: 0.5
Natty:
Report link

To complement @brunnerh's answer, you can compose this into a complete utility like so:

export function debounce<T>(f: (...args: T[]) => unknown, ms: number) {
  let id: null | number = null;
  return (...args: T[]) => {
    if (id) {
      clearTimeout(id);
    }
    id = setTimeout(() => {
      f(...args);
    }, ms);
  };
}

export function debounced<T>(stateGetter: () => T, ms: number) {
  let state = $state(stateGetter());
  const update = debounce<T>((v) => (state = v), ms);
  $effect(() => update(stateGetter()));

  return () => state;
}

Which you can then use like so:

  let getDebouncedSearch = debounced(() => search, 500)

However, debounced values are usually more useful for API calls and asynchronous requests. You generally don't need the debounced value itself in the UI, so you very probably do not need a signal for it.

What you probably need is simply:

const search = $state("");

$effect(() => {
  debounced(() => getSearchResults(search), 500);
});
Reasons:
  • Long answer (-0.5):
  • Has code block (-0.5):
  • User mentioned (1): @brunnerh's
  • Low reputation (0.5):
Posted by: ecstrema