Skip to main content

Overview

The useThrottle hooks limit how often a value updates or a function executes. Unlike debouncing, throttling guarantees execution at regular intervals, making it ideal for scroll handlers, mouse movements, and other high-frequency events.

Hooks

useThrottledValue

Returns a throttled version of a value that updates at most once every specified interval.
function useThrottledValue<T>(value: T, interval: number): T

Parameters

value
T
required
The value to throttle
interval
number
required
Minimum time in milliseconds between updates

Returns

throttledValue
T
The throttled value that updates at most once per interval

useThrottledCallback

Returns a throttled callback that fires at most once every specified interval.
function useThrottledCallback<T extends (...args: unknown[]) => void>(
  callback: T,
  interval: number
): (...args: Parameters<T>) => void

Parameters

callback
T
required
Function to throttle
interval
number
required
Minimum time in milliseconds between function calls

Returns

throttledCallback
function
A throttled callback that executes at most once per interval

Examples

Throttling search updates

import { useState } from 'react';
import { useThrottledValue } from '@kivora/react';

function SearchComponent() {
  const [search, setSearch] = useState('');
  const throttledSearch = useThrottledValue(search, 300);

  // This effect runs at most once every 300ms
  useEffect(() => {
    fetchResults(throttledSearch);
  }, [throttledSearch]);

  return (
    <input
      type="text"
      value={search}
      onChange={(e) => setSearch(e.target.value)}
    />
  );
}

Scroll position tracking

import { useEffect, useState } from 'react';
import { useThrottledCallback } from '@kivora/react';

function ScrollTracker() {
  const [scrollPos, setScrollPos] = useState(0);

  const handleScroll = useThrottledCallback(() => {
    setScrollPos(window.scrollY);
  }, 100);

  useEffect(() => {
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, [handleScroll]);

  return <div>Scroll position: {scrollPos}px</div>;
}

Mouse movement tracking

import { useState } from 'react';
import { useThrottledCallback } from '@kivora/react';

function MouseTracker() {
  const [position, setPosition] = useState({ x: 0, y: 0 });

  const updatePosition = useThrottledCallback((e: MouseEvent) => {
    setPosition({ x: e.clientX, y: e.clientY });
  }, 50);

  return (
    <div
      onMouseMove={updatePosition}
      style={{ width: '100%', height: '400px', border: '1px solid #ccc' }}
    >
      Mouse: ({position.x}, {position.y})
    </div>
  );
}

Auto-save with throttling

import { useThrottledCallback } from '@kivora/react';

function Editor() {
  const [content, setContent] = useState('');

  const throttledSave = useThrottledCallback((data: string) => {
    // Saves at most once per second, even if typing continuously
    api.saveDocument(data);
  }, 1000);

  const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    const newContent = e.target.value;
    setContent(newContent);
    throttledSave(newContent);
  };

  return <textarea value={content} onChange={handleChange} />;
}

Use Cases

  • Scroll handlers: Track scroll position without overwhelming the browser
  • Mouse/touch tracking: Monitor user interactions efficiently
  • Window resize: Update layout calculations at controlled intervals
  • Auto-save: Save changes periodically during continuous editing
  • API polling: Limit request frequency for real-time data

Throttle vs Debounce

  • Throttle: Guarantees execution at regular intervals (e.g., every 100ms)
  • Debounce: Waits for a pause in activity before executing
Use throttle for continuous events where you need regular updates. Use debounce when you only care about the final value after activity stops.

Build docs developers (and LLMs) love