React Tools
@galiprandi/react-tools is a lightweight, dependency-free utility library for React that provides reusable components and hooks to simplify development and improve accessibility — no configuration needed.
Installation
npm install @galiprandi/react-tools
# or
yarn add @galiprandi/react-tools
# or
pnpm add @galiprandi/react-tools
Components
AsyncBlock
Declarative component to render async data with loading, success, and error states. Automatically cancels in-flight requests when dependencies change.
<AsyncBlock
promiseFn={() => fetch(`/api/user`).then(res => res.json())}
pending={<p>Loading...</p>}
success={(data, reload) => (
<div>
<p>Welcome {data.name}</p>
<button
</div>
)}
error={(err, reload) => (
<div>
<p>Error: {(err as Error).message}</p>
<button
</div>
)}
timeOut={5000}
deps={[userId]}
/>
Props:
promiseFn: Async function returning a Promisepending: UI while loadingsuccess: UI on success (receives data and reload function)error: UI on error (receives error and reload function)timeOut: Optional timeout in msdeps: Dependency list for re-executiononSuccess: Optional success callbackonError: Optional error callback
Recommended Use Cases:
- API Data Fetching: Load user profiles, product details, or any REST API data with automatic cancellation when the component unmounts or dependencies change
- Search Results: Display search results with loading states and error handling, automatically refetching when search terms change
- Dashboard Metrics: Fetch and display real-time metrics with periodic refresh via the
depsarray - Form Submission: Handle async form submissions with loading states during POST/PUT requests
- Lazy Loading: Load data only when needed (e.g., when a tab becomes active) by controlling execution through the
depsarray
Form
Enhanced <form> element that automatically gathers and returns values on submit.
<Form<{ username: string }> filterEmptyValues>
<Input name="username" label="Username" />
<button type="submit">Submit</button>
</Form>
Props:
onSubmitValues: Handles form submission with collected valuesfilterEmptyValues: Remove empty fields before submission (default: false)
Recommended Use Cases:
- User Registration/Login: Collect and validate user credentials with automatic value gathering and optional empty field filtering
- Contact Forms: Handle contact form submissions with built-in transformations (e.g., titleCase for names, onlyEmail for emails)
- Settings Pages: Manage user preferences and configuration settings with type-safe value collection
- Search Filters: Create filter forms that automatically collect and transform filter values before API calls
- Data Entry Forms: Streamline data entry workflows with automatic value collection and optional filtering of empty fields
Input
Custom input component supporting transformations, debounce, datalist, and more.
<Input
label="Email"
name="email"
placeholder="Enter your email"
transform="onlyEmail"
=> console.log(val)}
debounceDelay={500}
/>
// Multiple transforms applied sequentially
<Input
label="Username"
transform={['toUpperCase', 'onlyAlphanumeric']}
=> console.log(val)}
/>
Props:
label: Optional labeltransform: Built-in value transforms (camelCase, pascalCase, kebabCase, titleCase, onlyEmail, etc.) - can be a single transform or an array of transforms applied sequentiallytransformFn: Custom value transform functiononChangeValue: Fires on value changeonChangeDebounce: Fires after debouncedebounceDelay: Delay in millisecondsdatalist: List of autocomplete suggestions
Recommended Use Cases:
- Email Validation: Use
transform="onlyEmail"to ensure proper email format with automatic validation - Name Formatting: Apply
transform="titleCase"to automatically capitalize names and titles - Search Inputs: Leverage
debounceDelayandonChangeDebouncefor search/filter inputs to reduce API calls - Autocomplete Fields: Use
datalistprop to provide suggestions for city names, product names, or any predefined options - URL/Slug Fields: Apply
transform="kebabCase"ortransform="snakeCase"for URL-friendly slugs - Numeric Inputs: Use
transform="onlyNumbers"to restrict input to numeric values only
DateTime
Wrapper around <input type="datetime-local" /> that handles ISO string conversion.
<DateTime
label="Appointment"
isoValue={value}
/>
Props:
isoValue: ISO 8601 datetime valueonChangeISOValue: Callback with ISO string- Inherits all
<Input />props
Recommended Use Cases:
- Appointment Scheduling: Schedule meetings, appointments, or events with ISO string storage for consistent timezone handling
- Event Creation: Create events with datetime inputs that automatically convert to ISO format for database storage
- Deadline Management: Set deadlines or due dates with proper ISO string conversion for backend APIs
- Booking Systems: Handle booking dates and times for reservations, flights, or services
- Time Tracking: Record start/end times for tasks or activities with ISO format consistency
Dialog
Accessible dialog/modal component built on top of the native <dialog> element.
<Dialog
behavior="modal"
opener={<button>Open Modal</button>}
=> console.log('Closed')}
>
<p>This is a dialog!</p>
</Dialog>
Props:
isOpen: Controlled open state (optional)behavior: Dialog type ('dialog' | 'modal', default: 'modal')onOpen: Triggered on openonClose: Triggered on closeopener: Element to trigger openingchildren: Content inside the dialog- Inherits all native
<dialog>props
Recommended Use Cases:
- Confirmation Dialogs: Show confirmation prompts before destructive actions (delete, cancel, etc.) with accessible keyboard support
- Modal Forms: Display forms in modals for creating/editing items without leaving the current context
- Alert/Notification Modals: Show important alerts, warnings, or information messages with proper ARIA roles
- Detail Views: Display detailed information about an item in a modal overlay while maintaining page context
- Settings Panels: Open settings or configuration panels as accessible dialogs with focus management
Observer
Tracks whether a child element is visible in the viewport using IntersectionObserver. Triggers callbacks when the element appears or disappears.
<Observer
wrapper="section"
=> console.log('Element appeared')}
=> console.log('Element disappeared')}
threshold={0.5}
>
<div>Watch me appear!</div>
</Observer>
Props:
wrapper: HTML element to wrap children with (default: 'div')onAppear: Callback when element appears in viewportonDisappear: Callback when element disappears from viewportthreshold: Intersection threshold (0-1)root: The element used as the viewportrootMargin: Margin around the root- Extends
IntersectionObserverInitoptions
Recommended Use Cases:
- Scroll Animations: Trigger animations when elements enter the viewport (fade-in, slide-up effects)
- Infinite Scroll: Detect when user reaches bottom of list to load more items
- Analytics Tracking: Track when content becomes visible to users for analytics purposes
- Lazy Loading Images: Load images only when they come into view (though LazyRender is better for this)
- Progress Indicators: Show progress indicators when sections become visible during scrolling
- Active Navigation: Highlight navigation items based on which section is currently visible
LazyRender
Only renders children when they become visible in the viewport. Automatically unmounts children when they disappear to optimize performance.
<LazyRender
wrapper="section"
placeholder={<span>Loading...</span>}
threshold={0.5}
>
<img src="/heavy-image.jpg" alt="Lazy" />
</LazyRender>
Props:
wrapper: HTML element to wrap children with (default: 'div')placeholder: Rendered before children become visiblethreshold: Intersection threshold (0-1)root: The element used as the viewportrootMargin: Margin around the root- Extends
IntersectionObserverInitoptions
Hooks
useAI
Hook for checking and managing the availability of browser's AI APIs. Provides a centralized way to detect which AI APIs are available, track model download progress, and preload models. Supports current APIs (Summarizer, Translator, LanguageDetector) and experimental APIs (Prompt, Writer, Rewriter, Proofreader).
import { useAI } from '@galiprandi/react-tools';
function MyComponent() {
// Check all APIs
const { isAvailable, apis, status } = useAI();
// Check specific APIs
const { isAvailable, apis, preload } = useAI({ apis: ['translator', 'summarizer'] });
// Preload models
useEffect(() => {
if (isAvailable) {
preload('translator');
}
}, [isAvailable, preload]);
// Show download progress
if (apis.translator.availability === 'downloading') {
const progress = apis.translator.progress;
return <LoadingBar {...progress} />;
}
}
Options:
apis: Specific APIs to check (if not provided, checks all APIs)onProgress: Callback when an API's download progress updatesonReady: Callback when an API becomes ready
Returns:
isAvailable: Whether any of the requested APIs are availablestatus: Current status of the availability checkerror: Error object if the check failedapis: Status of each APIisApiAvailable: Check if a specific API is availablegetApiProgress: Get download progress for a specific APIpreload: Preload a specific API's modelpreloadAll: Preload all APIs' models
Supported APIs: summarizer, translator, languageDetector, prompt (Experimental), writer (Experimental), rewriter (Experimental), proofreader (Experimental)
Note: Requires Chrome's Native AI APIs, which are currently experimental.
Recommended Use Cases:
- Feature Detection: Check if AI features are available before showing AI-powered UI components
- Model Preloading: Preload AI models during app initialization for faster first use
- Progress Tracking: Show download progress when AI models are being downloaded
- Conditional Rendering: Conditionally render AI features based on API availability
- Multi-API Apps: Apps that use multiple AI APIs (summarizer, translator, etc.) need to check availability for each
useAISummarize
Hook for using the browser's AI Summarizer API. Provides a React interface to Chrome's native AI Summarizer API with model initialization, download progress, streaming support, and automatic cleanup.
import { useAISummarize } from '@galiprandi/react-tools';
function MyComponent() {
const summarize = useAISummarize({
type: 'tldr',
format: 'markdown',
length: 'short',
outputLanguage: 'en',
streaming: true
});
const handleSummarize = async () => {
await summarize.summarize(longText, 'End the summary with: Powered by my app');
console.log(summarize.data);
};
return (
<div>
<button
{summarize.status === 'summarizing' && <p>Summarizing...</p>}
{summarize.data && <p>{summarize.data}</p>}
</div>
);
}
Options:
type: Type of summary ('tldr' | 'key-points' | 'teaser' | 'headline')format: Output format ('plain-text' | 'markdown')length: Length of the summary ('short' | 'medium' | 'long')sharedContext: Shared context for all summariesexpectedInputLanguages: Expected input languages (BCP 47 format)outputLanguage: Output language ('en' | 'es' | 'ja' | 'auto' | 'user')expectedContextLanguages: Expected context languages (BCP 47 format)preference: Performance preference ('auto' | 'capability')streaming: Enable streaming output (default: false)warmup: Preload model on mount (default: false)
Returns:
data: The generated summary textstatus: Current status of the summarization processprogress: Download progress if model is being downloadederror: Error object if summarization failedsupportedPreferences: Supported preference values based on browser capabilitiessummarize: Function to summarize text with optional context instructionreset: Function to reset the hook state
Note: Requires Chrome's AI Summarizer API, which is currently experimental.
Recommended Use Cases:
- Article Summaries: Generate TL;DR summaries of long articles or blog posts
- Document Review: Summarize long documents or reports for quick overview
- Meeting Notes: Condense meeting transcripts into key points
- Content Preview: Show summaries of content before users click to read full text
- Email Digests: Summarize email threads for quick understanding
useAIPrompt
Hook for using the browser's Prompt API with multimodal support. Provides a React interface to Chrome's native Prompt API with model initialization, download progress, streaming support, automatic cleanup, and automatic type inference for text, images, and audio.
import { useAIPrompt } from '@galiprandi/react-tools';
function MyComponent() {
const { data, prompt, append, status } = useAIPrompt({
initialPrompts: [
{ role: 'system', content: 'You are a helpful assistant.' }
],
expectedInputs: [{ type: 'text' }, { type: 'image' }],
expectedOutputs: [{ type: 'text' }]
});
const handleSendWithImage = async (imageBlob: Blob) => {
await prompt([
{ role: 'user', content: ['Describe this image:', imageBlob] }
]);
};
const handleAppendImage = async (imageBlob: Blob) => {
await append([
{ role: 'user', content: ['Reference image:', imageBlob] }
]);
};
return (
<div>
<button => prompt('What is the capital of France?')} disabled={status === 'prompting'}>
Send
</button>
{status === 'prompting' && <p>Thinking...</p>}
<p>{data}</p>
</div>
);
}
Multimodal Support:
The hook supports automatic type inference for:
- Text: strings
- Audio: AudioBuffer, ArrayBuffer, ArrayBufferView, Blob (audio/*)
- Images: HTMLImageElement, SVGImageElement, HTMLVideoElement, HTMLCanvasElement, ImageBitmap, OffscreenCanvas, VideoFrame, Blob (image/*), ImageData
Options:
initialPrompts: Initial system/context promptstemperature: Sampling temperature (0.0-1.0)topK: Top-K sampling parameterstreaming: Enable streaming output (default: false)warmup: Preload model on mount (default: true)expectedInputs: Expected input types for multimodal support (e.g.,[{ type: 'text' }, { type: 'image' }])expectedOutputs: Expected output types (e.g.,[{ type: 'text' }])
Returns:
data: The generated response textstatus: Current status of the prompt processprogress: Download progress if model is being downloadederror: Error object if prompting failedprompt: Function to send a prompt to the AI (supports text or multimodal content)append: Function to append contextual messages without generating response (useful for preloading images/audio)reset: Function to reset the hook statecontextUsage: Number of tokens used in current sessioncontextWindow: Maximum number of tokens allowed
Multimodal Examples:
// Image analysis
const imageBlob = await fetch('photo.jpg').then(r => r.blob());
await prompt([
{ role: 'user', content: ['What do you see in this image?', imageBlob] }
]);
// Canvas drawing analysis
await prompt([
{ role: 'user', content: ['Analyze this drawing:', canvasElement] }
]);
// Audio transcription
const audioBuffer = await captureAudio();
await prompt([
{ role: 'user', content: ['Transcribe this audio:', audioBuffer] }
]);
// Preload images with append, then ask question
await append([{ role: 'user', content: ['Image 1:', image1] }]);
await append([{ role: 'user', content: ['Image 2:', image2] }]);
await prompt('Compare these two images');
Important Limitations:
- Single content type per prompt: The Chrome AI model currently has limitations processing multiple content types (e.g., image + audio) simultaneously in a single prompt. Send one type of multimodal content at a time for best results.
- Model capability: Multimodal support depends on the specific Chrome AI model version and capabilities available in the browser.
Note: Requires Chrome's Prompt API, which is currently experimental.
Recommended Use Cases:
- AI Chat Interfaces: Build chat interfaces with streaming responses and context management
- Image Analysis: Analyze uploaded images, canvas drawings, or video frames
- Audio Processing: Transcribe audio or process voice inputs
- Content Generation: Generate text content with configurable creativity and sampling
- Question Answering: Answer questions with context-aware responses
- Multimodal AI: Combine text, images, and audio in a single prompt
useAIWrite
Hook for using the browser's Writer API to generate written content with customizable tone and format. Provides a React interface to Chrome's native Writer API with model initialization, download progress, streaming support, shared context management, and automatic cleanup.
import { useAIWrite } from '@galiprandi/react-tools';
function MyComponent() {
const { data, write, status, progress } = useAIWrite({
tone: 'formal',
format: 'markdown',
length: 'medium',
sharedContext: 'This is for a professional business email',
streaming: true
});
const handleWrite = async () => {
await write('Write a thank you email to a colleague for their help on the project', 'I want to mention their attention to detail');
};
return (
<div>
<button disabled={status === 'writing'}>
Generate
</button>
{status === 'writing' && <p>Writing...</p>}
{status === 'downloading' && <p>Downloading model...</p>}
{data && <p>{data}</p>}
</div>
);
}
Options:
tone: Writing tone ('formal' | 'neutral' | 'casual', default: 'neutral')format: Output format ('markdown' | 'plain-text', default: 'markdown')length: Length of the output ('short' | 'medium' | 'long', default: 'short')sharedContext: Shared context for all writing tasks (helps maintain consistency across multiple writes)outputLanguage: Output language (BCP 47 format, e.g., 'en', 'es', 'fr')expectedInputLanguages: Expected input languages (BCP 47 format)expectedContextLanguages: Expected context languages (BCP 47 format)streaming: Enable streaming output (default: false)warmup: Preload model on mount (default: true)
Returns:
data: The generated written contentstatus: Current status of the writing processprogress: Download progress if model is being downloadederror: Error object if writing failedwrite: Function to generate written content with optional contextreset: Function to reset the hook state
Note: Requires Chrome's Writer API, which is currently experimental.
Recommended Use Cases:
- Email Generation: Generate professional or casual emails (thank you, follow-up, introduction)
- Blog Post Writing: Create blog posts with customizable tone and length
- Social Media Content: Generate social media posts with appropriate formatting
- Document Drafting: Draft reports, proposals, or documentation
- Marketing Copy: Create marketing materials with consistent tone
- Content Templates: Generate content templates with shared context for consistency
useAIRewriter
Hook for using the browser's Rewriter API to rewrite and restructure text with customizable tone, format, and length. Provides a React interface to Chrome's native Rewriter API with model initialization, download progress, streaming support, shared context management, and automatic cleanup.
import { useAIRewriter } from '@galiprandi/react-tools';
function MyComponent() {
const { data, rewrite, status, progress } = useAIRewriter({
tone: 'more-formal',
format: 'markdown',
length: 'shorter',
sharedContext: 'This is for a professional business email',
streaming: true
});
const handleRewrite = async () => {
await rewrite('Hi, I wanted to let you know the project is going well.', 'Make it more professional');
};
return (
<div>
<button disabled={status === 'rewriting'}>
Rewrite
</button>
{status === 'rewriting' && <p>Rewriting...</p>}
{status === 'downloading' && <p>Downloading model...</p>}
{data && <p>{data}</p>}
</div>
);
}
Options:
tone: Writing tone ('more-formal' | 'as-is' | 'more-casual', default: 'as-is')format: Output format ('as-is' | 'markdown' | 'plain-text', default: 'as-is')length: Length of the output ('shorter' | 'as-is' | 'longer', default: 'as-is')sharedContext: Shared context for all rewriting tasks (helps maintain consistency across multiple rewrites)outputLanguage: Output language (BCP 47 format, e.g., 'en', 'es', 'fr')expectedInputLanguages: Expected input languages (BCP 47 format)expectedContextLanguages: Expected context languages (BCP 47 format)streaming: Enable streaming output (default: false)warmup: Preload model on mount (default: true)
Returns:
data: The rewritten textstatus: Current status of the rewriting processprogress: Download progress if model is being downloadederror: Error object if rewriting failedrewrite: Function to rewrite text with optional context and tone overridereset: Function to reset the hook state
Note: Requires Chrome's Rewriter API, which is currently experimental.
Recommended Use Cases:
- Email Tone Adjustment: Make emails more professional or casual
- Content Condensation: Summarize or condense long text
- Content Expansion: Add detail and elaboration to brief content
- Style Improvement: Enhance readability and flow of text
- Audience Adaptation: Rewrite content for different audiences
- Review Polishing: Improve feedback constructiveness
- Format Conversion: Convert content to markdown or plain-text
useAIProofreader
Hook for using the browser's Proofreader API to check grammar and spelling with highlighted corrections. Provides a React interface to Chrome's native Proofreader API with model initialization, download progress, and automatic cleanup.
import { useAIProofreader } from '@galiprandi/react-tools';
function MyComponent() {
const { data, corrections, proofread, status } = useAIProofreader({
expectedInputLanguages: ['en'],
});
const handleProofread = async () => {
await proofread('I seen him yesterday at the store.');
};
return (
<div>
<button disabled={status === 'proofreading'}>
Proofread
</button>
{status === 'proofreading' && <p>Proofreading...</p>}
{data && <p>{data}</p>}
{corrections.length > 0 && (
<ul>
{corrections.map((c, i) => (
<li key={i}>
{c.type && <span>Type: {c.type}</span>}
{c.explanation && <span> - {c.explanation}</span>}
</li>
))}
</ul>
)}
</div>
);
}
Options:
expectedInputLanguages: Expected input languages (BCP 47 format, e.g., 'en', 'es')warmup: Preload model on mount (default: true)
Returns:
data: The corrected textcorrections: Array of corrections with startIndex, endIndex, type, and explanationstatus: Current status of the proofreading processprogress: Download progress if model is being downloadederror: Error object if proofreading failedproofread: Function to proofread textreset: Function to reset the hook state
ProofreadCorrection:
startIndex: Start index of the correction in the original textendIndex: End index of the correction in the original texttype: Type of correction (e.g., 'grammar', 'spelling')explanation: Explanation of the correction
Note: Requires Chrome's Proofreader API, which is currently experimental.
Recommended Use Cases:
- Text Editing: Grammar and spell checking in text editors
- Content Review: Improving writing quality before publishing
- Email Validation: Catching typos before sending emails
- Document Proofreading: Ensuring professional quality in documents
- Blog Post Review: Improving readability of blog content
- Comment Moderation: Identifying language issues in user comments
useLanguageDetection
Hook for using the browser's Language Detection API. Provides a React interface to Chrome's native Language Detection API with model initialization, download progress, and automatic cleanup. Returns the most likely detected language, confidence score, all results, and user language comparison.
import { useLanguageDetection } from '@galiprandi/react-tools';
function MyComponent() {
const { lang, confidence, allLangs, userLang, isUserLang, status } = useLanguageDetection({
text: 'Hallo und herzlich willkommen!',
minConfidence: 0.8
});
return (
<div>
{status === 'detecting' && <p>Detecting...</p>}
{lang && (
<p>
Detected: {lang} ({Math.round(confidence! * 100)}% confidence)
{isUserLang && <span> (matches your language)</span>}
</p>
)}
{allLangs.length > 1 && (
<details>
<summary>All detected languages</summary>
<ul>
{allLangs.map(({ lang, confidence }) => (
<li key={lang}>{lang}: {Math.round(confidence * 100)}%</li>
))}
</ul>
</details>
)}
</div>
);
}
Options:
text: Text to detect language from (re-detects automatically when changed)enable: Enable/disable auto-detection (default: true)warmup: Preload the model on component mount (default: false)minConfidence: Minimum confidence to include in allLangs (0.0 - 1.0, default: 0)maxResults: Maximum number of results to return in allLangs
Returns:
lang: The most likely detected language codeconfidence: Confidence of the most likely detection (0.0 - 1.0)allLangs: All detected languages with confidence scoresuserLang: User's browser language codeisUserLang: Whether detected language matches user's browser languagestatus: Current status of the detection processprogress: Download progress if model is being downloadederror: Error object if detection failedreset: Function to reset the hook state
Note: Requires Chrome's Language Detection API, which is currently experimental.
Recommended Use Cases:
- Content Language Detection: Detect the language of user-generated content (comments, reviews, posts)
- Auto-Localization: Automatically detect content language to apply appropriate formatting or UI
- Language-Based Routing: Route users to language-specific content based on detected text language
- Content Moderation: Detect language for language-specific moderation rules
- Analytics: Track language distribution of user-generated content
useTranslator
Hook for using the browser's Translator API. Provides a React interface to Chrome's native Translator API with model initialization, download progress, streaming support, and automatic cleanup. Supports 38+ languages. Automatically detects source language and uses browser language by default. Optimization: When detected source language matches target language, returns original text without loading translation model.
import { useTranslator } from '@galiprandi/react-tools';
function MyComponent() {
// Auto-detect source language and translate to browser language
const { data, detectedSourceLanguage, resolvedTargetLanguage, status } = useTranslator({
text: 'Hello world, how are you?'
});
return (
<div>
{status === 'translating' && <p>Translating...</p>}
{data && (
<p>
{data}
{detectedSourceLanguage && <small> (from {detectedSourceLanguage} to {resolvedTargetLanguage})</small>}
</p>
)}
</div>
);
}
Options:
text: Text to translate (auto-translates when changed)sourceLanguage: Source language code ('auto' or specific language, default: 'auto')targetLanguage: Target language code ('user' or specific language, default: 'user')streaming: Enable streaming output (default: false)warmup: Preload model on mount (default: false)enable: Enable/disable auto-translation (default: true)
Returns:
data: The translated textdetectedSourceLanguage: Detected source language (when sourceLanguage is 'auto')resolvedTargetLanguage: Resolved target language (when targetLanguage is 'user')status: Current status of the translation processprogress: Download progress if model is being downloadederror: Error object if translation failedtranslate: Function to translate text manuallyreset: Function to reset the hook state
Supported Languages: ar, bg, bn, cs, da, de, el, en, es, fi, fr, hi, hr, hu, id, it, iw, ja, kn, ko, lt, mr, nl, no, pl, pt, ro, ru, sk, sl, sv, ta, te, th, tr, uk, vi, zh, zh-Hant
Note: Requires Chrome's Translator API, which is currently experimental.
Recommended Use Cases:
- Real-time Translation: Translate user input in real-time as they type
- Content Localization: Automatically translate content to user's browser language
- Multi-language Apps: Build apps that support multiple languages with automatic translation
- Cross-language Communication: Enable communication between users speaking different languages
- Document Translation: Translate documents or articles on-demand for international users
useDebounce
A React hook that returns a debounced version of a value. Useful for search input, filters, etc.
const debouncedSearch = useDebounce(searchTerm, 500);
Parameters:
value: Value to debouncedelay: Delay in milliseconds
Returns: Debounced version of the value.
Recommended Use Cases:
- Search Inputs: Debounce search terms to reduce API calls while typing
- Filter Inputs: Delay filter application until user stops typing
- Auto-save: Debounce auto-save functionality to save only after user stops editing
- API Rate Limiting: Reduce API call frequency for expensive operations
- Validation: Delay form validation until user stops typing
useTimer
A React hook that abstracts the complexity of managing setTimeout and setInterval directly in React components. Provides automatic cleanup, lifecycle events, flexible scheduling, and simplified control to prevent memory leaks.
Features:
- Automatic cleanup when component unmounts
- Lifecycle events (set, cancel, complete, progress)
- Flexible scheduling (milliseconds, Date, limited intervals)
- Simplified control with single clear method
import { useEffect } from 'react';
import { useTimer } from '@galiprandi/react-tools';
function FutureExecution({ targetDate }: { targetDate: Date }) {
const { setTimeoutDate, clearTimer } = useTimer({
onSetTimer: (id) => console.log(`Timer ID ${id} set for future execution`),
onTimerComplete: (id) => console.log(`Timer ID ${id} completed!`),
onCancelTimer: (id) => console.log(`Timer ID ${id} cancelled!`),
onProgress: (progress) =>
console.log(`Progress: ${Math.round(progress * 100)}%`),
});
useEffect(() => {
setTimeoutDate(() => {
console.log("--- Fake fetch executed! ---");
}, targetDate);
return () => {
clearTimer();
};
}, [setTimeoutDate, clearTimer, targetDate]);
return <p>Check the console for timer messages.</p>;
}
Parameters (options):
onSetTimer: Callback fired when a new timer is successfully setonCancelTimer: Callback fired when an active timer is cleared/cancelledonTimerComplete: Callback fired when a timer completes naturallyonProgress: Callback fired periodically during long timers to report progress (0 to 1)
Returns:
setTimeout: Sets a timeout with event callbacks (accepts milliseconds or a Date)setInterval: Sets an interval with event callbacks (accepts milliseconds)setTimeoutDate: Sets a timeout to execute at a specific future DatesetLimitedInterval: Sets an interval that executes a fixed number of timesclearTimer: Clears any currently active timerisActive: Returns true if a timer is currently activegetCurrentTimerId: Returns the ID of the currently active timergetRemainingIterations: ForsetLimitedInterval, returns remaining executionsgetRemainingTime: For an activesetTimeout, returns estimated remaining time in ms
Recommended Use Cases:
- Scheduled Actions: Execute actions at specific times or dates (e.g., send notifications at a future time)
- Countdown Timers: Display countdown timers for events, deadlines, or expiration dates
- Polling: Poll APIs at regular intervals to check for updates
- Progress Tracking: Track progress of long-running operations with progress callbacks
- Auto-refresh: Refresh data at intervals (e.g., stock prices, live scores)
- Session Timeouts: Implement session timeout warnings or automatic logout
useList
A React hook that simplifies managing array state in components. Provides immutable helper methods for common operations like adding, inserting, removing, updating, finding, and counting items based on index or item properties.
Parameters:
initialList: The initial array state (defaults to [])
Returns: An object containing the current array state (list) and helper functions to modify or query it immutably.
Properties:
list: The current array stateaddItem: Adds an item to the end of the arrayinsert: Inserts an item at the specified indexinsertMany: Adds multiple items to the end of the arrayremoveByIdx: Removes the item at the specified indexremoveBy: Removes the first item where item[key] equals valueremoveManyBy: Removes all items where item[key] equals valueupdateByIdx: Updates the item at the specified index using an update functionupdateBy: Updates the first item where item[key] equals valueupdateManyBy: Updates all items where item[key] equals valueclearList: Removes all items from the listsetList: Replaces the entire list arrayfindItemBy: Finds and returns the first item where item[key] equals valuefindItemsBy: Finds and returns all items where item[key] equals valuecount: Returns the total number of items, or count matching an optional predicatetoggle: Adds an item if not present, or removes it if it ismove: Moves an item from one index to another immutablysort: Sorts the list immutably using an optional comparison functionshuffle: Randomly reorders the list items immutably
Recommended Use Cases:
- Todo Lists: Manage todo items with add, remove, toggle, and update operations
- Shopping Carts: Handle cart items with quantity updates, removal, and total calculations
- Data Tables: Manage table data with sorting, filtering, and row operations
- Tag Management: Add/remove tags with toggle functionality
- Playlist Management: Manage playlist items with reorder, remove, and add operations
- Form Field Arrays: Handle dynamic form fields (e.g., multiple email addresses, phone numbers)
Accessibility & Performance
All components follow accessibility best practices:
- ✅
Dialoguses proper ARIA roles and keyboard focus control - ✅
Inputsupports labeling, aria attributes, and datalists - ✅
LazyRenderandObserveruseIntersectionObserverto optimize rendering
FAQ
Q: Is this compatible with React Native?
A: No, this library is intended for use in React DOM (web).
Q: Can I style components with Tailwind or CSS modules?
A: Yes, components are unstyled and fully customizable.
Q: Does it support SSR or work in Next.js?
A: Yes, all components are compatible with SSR environments.
Q: How can I report a bug or request a new feature?
A: Open an issue on the GitHub repo.