Interval Hooks
Preactor provides custom hooks for working with intervals in your components. These hooks simplify the process of setting up and cleaning up intervals, helping you avoid memory leaks and ensuring proper lifecycle management.
Features
Section titled “Features”- Automatic cleanup of intervals when components unmount
- Dependency array support for controlling when intervals are reset
- State management integration with
useIntervalState
- Type-safe implementation with TypeScript
How It Works
Section titled “How It Works”The interval hooks leverage Preact’s useEffect
hook to properly manage the lifecycle of setInterval
calls:
- When a component mounts, the interval is created
- When the component unmounts, the interval is automatically cleared
- When dependencies change, the interval is reset
Available Hooks
Section titled “Available Hooks”useInterval
Section titled “useInterval”The useInterval
hook sets up an interval that automatically cleans up when the component unmounts.
function useInterval( delay: number, callback: () => void, inputs: ReadonlyArray<unknown>): void
Parameters
Section titled “Parameters”Parameter | Type | Description |
---|---|---|
delay | number | The interval delay in milliseconds |
callback | () => void | The function to call on each interval |
inputs | ReadonlyArray<unknown> | Dependencies that will reset the interval when changed |
useIntervalState
Section titled “useIntervalState”The useIntervalState
hook combines interval functionality with state management. It periodically updates a state value based on the callback function.
function useIntervalState<T>( delay: number, callback: () => T, inputs?: ReadonlyArray<unknown>): T
Parameters
Section titled “Parameters”Parameter | Type | Description |
---|---|---|
delay | number | The interval delay in milliseconds |
callback | () => T | Function that returns the new state value |
inputs | ReadonlyArray<unknown> (optional) | Dependencies that will reset the interval when changed |
Return Value
Section titled “Return Value”Returns the current state value of type T
.
Usage Examples
Section titled “Usage Examples”Basic Interval
Section titled “Basic Interval”import { useInterval } from 'preactor';
function TickingClock() { const [seconds, setSeconds] = useState(0);
useInterval(1000, () => { setSeconds(prev => prev + 1); }, []);
return <div>Seconds elapsed: {seconds}</div>;}
Interval with Dependencies
Section titled “Interval with Dependencies”import { useInterval } from 'preactor';
function CountdownTimer({ startFrom, onComplete }) { const [count, setCount] = useState(startFrom);
useInterval(1000, () => { if (count > 0) { setCount(prev => prev - 1); } else { onComplete(); } }, [count, onComplete]);
return <div>Time remaining: {count} seconds</div>;}
Using useIntervalState
Section titled “Using useIntervalState”import { useIntervalState } from 'preactor';
function ServerStatusMonitor({ serverId }) { const status = useIntervalState( 5000, () => fetchServerStatus(serverId), [serverId] );
return ( <div> <h2>Server Status</h2> <div>Status: {status.isOnline ? 'Online' : 'Offline'}</div> <div>Last updated: {new Date().toLocaleTimeString()}</div> </div> );}
Implementation
Section titled “Implementation”import { useEffect, useState } from 'preact/hooks';
type Inputs = ReadonlyArray<unknown>;
export function useInterval(delay: number, callback: () => void, inputs: Inputs) { useEffect(() => { const interval = setInterval(callback, delay); return () => clearInterval(interval); }, [...inputs, delay]);}
export function useIntervalState<T>(delay: number, callback: () => T, inputs?: Inputs) { const [state, setState] = useState(callback()); useInterval(delay, () => setState(callback()), inputs ? inputs : []);
useEffect(() => setState(callback()), inputs ? inputs : []); return state;}
Best Practices
Section titled “Best Practices”-
Choose appropriate intervals: Be mindful of performance implications when setting interval durations. Very short intervals (< 100ms) can cause performance issues.
-
Use the dependency array properly: Include all variables referenced in your callback function in the dependency array to avoid stale closures.
-
Handle cleanup for long-running components: The hooks automatically clean up intervals when components unmount, but for long-running components, consider adding manual cleanup logic if the interval is no longer needed.
-
Avoid expensive operations in interval callbacks: Keep interval callbacks lightweight. For expensive operations, consider using web workers or throttling techniques.
-
Set reasonable polling intervals for calls: When using
useIntervalState
for data polling, use reasonable intervals (0.5-2 seconds) to avoid overwhelming the Unity. -
Handle error cases: When using
useIntervalState
with API calls, ensure your callback function handles errors gracefully:
const data = useIntervalState( 5000, async () => { try { return await fetchData(); } catch (error) { console.error('Failed to fetch data:', error); return { error: true, message: error.message }; } }, []);
- Consider using a dynamic delay: For advanced use cases, you might want to adjust the delay based on certain conditions:
// Exponential backoff for failed requestsconst [delay, setDelay] = useState(1000);const [retries, setRetries] = useState(0);
useInterval(delay, async () => { try { const result = await fetchData(); // Reset on success setDelay(1000); setRetries(0); } catch (error) { // Increase delay with each retry (up to 30 seconds) setRetries(prev => prev + 1); setDelay(Math.min(30000, 1000 * Math.pow(2, retries))); }}, [delay, retries]);
Next Steps
Section titled “Next Steps”Now that you understand how to use interval hooks, you might want to explore:
- Button Component - Learn how to create interactive UI elements
- Localization - Add multi-language support to your UI
- Extensions - Discover how to extend Preactor’s functionality
For more examples, check out the Examples section.