Skip to main content
Keeps local state but throttles state updates triggered through the returned setter. Pending throttled updates are cleared on unmount.

Signature

function useThrottledState<T>(
  defaultValue: T,
  wait: number
): readonly [T, (value: T) => void]

Parameters

defaultValue
T
required
Initial state value.
wait
number
required
Throttle window in milliseconds for setter calls.

Returns

result
readonly [T, (value: T) => void]
A tuple containing the current value and a throttled setter function.

Usage

Throttled counter

import { useThrottledState } from '@kuzenbo/hooks';

function Counter() {
  const [count, setCount] = useThrottledState(0, 1000);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment (throttled)
      </button>
    </div>
  );
}

Throttled slider

import { useThrottledState } from '@kuzenbo/hooks';
import { useEffect } from 'react';

function VolumeControl() {
  const [volume, setVolume] = useThrottledState(50, 100);

  useEffect(() => {
    // Update audio volume
    const audio = document.querySelector('audio');
    if (audio) {
      audio.volume = volume / 100;
    }
  }, [volume]);

  return (
    <div>
      <label>Volume: {volume}%</label>
      <input
        type="range"
        min="0"
        max="100"
        value={volume}
        onChange={(e) => setVolume(Number(e.target.value))}
      />
    </div>
  );
}

Throttled position tracking

import { useThrottledState } from '@kuzenbo/hooks';
import { useEffect } from 'react';

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

  useEffect(() => {
    const handleMouseMove = (e: MouseEvent) => {
      setPosition({ x: e.clientX, y: e.clientY });
    };

    window.addEventListener('mousemove', handleMouseMove);
    return () => window.removeEventListener('mousemove', handleMouseMove);
  }, []);

  return (
    <div>
      Mouse position: {position.x}, {position.y}
    </div>
  );
}

Throttled form updates

import { useThrottledState } from '@kuzenbo/hooks';
import { useEffect } from 'react';

function AutoSaveForm() {
  const [formData, setFormData] = useThrottledState(
    { name: '', email: '' },
    2000
  );

  useEffect(() => {
    if (formData.name || formData.email) {
      fetch('/api/autosave', {
        method: 'POST',
        body: JSON.stringify(formData)
      });
    }
  }, [formData]);

  return (
    <form>
      <input
        placeholder="Name"
        onChange={(e) => setFormData({ ...formData, name: e.target.value })}
      />
      <input
        placeholder="Email"
        onChange={(e) => setFormData({ ...formData, email: e.target.value })}
      />
    </form>
  );
}

Build docs developers (and LLMs) love