Hooks
The Hooks
namespace includes functions to create user hooks:
useClickOutside
- perform the effect when the user clicks outside the elementuseCompose
- create a composed functionuseCookie
- manage a cookieuseCurry
- create a curried functionuseDebounce
- create a debounced functionuseEvent
- create an event listeneruseId
- create id for the elementuseInterval
- create an intervaluseMediaQuery
- check a media queryuseMemo
- memoization functionusePipe
- create a piped functionuseQueue
- create a queueuseState
- create a state variable and a function to change ituseThrottle
- create a throttled functionuseToggle
- create a toggle function
Installation
Section titled “Installation”Metro UI already includes the Hooks
.
You can use it without any additional installation, but if you want to use it in your project, you can install it with package manager:
npm install @olton/hooks
pnpm install @olton/hooks
yarn add @olton/hooks
or use CDN:
<script type="module"> import * as Hooks from "https://esm.run/@olton/hooks";</script>
useClickOutside()
Section titled “useClickOutside()”useClickOutside
is a hook to detect when a click occurs outside of a given DOM element.
The function accepts a target element
and a callback
function.
If a click event happens outside of the specified element, the callback
will be executed.
const myDiv = document.getElementById('my-div');const handleOutsideClick = () => { console.log('Clicked outside the div!');};
const { attach, detach } = useClickOutside(myDiv, handleOutsideClick);
// Attach the click listenerattach();
// Later, if you need to remove the listenerdetach();
useCompose()
Section titled “useCompose()”useCompose
is a hook for the composition of functions (performance from right to left)
f(g(h(x))) => compose(f, g, h)(x)
const add = (x: number) => x + 1;const multiply = (x: number) => x * 2;const subtract = (x: number) => x - 3;
// f(g(h(x))) => subtract(multiply(add(x)))const composedMath = useCompose(subtract, multiply, add);const result = composedMath(5); // ((5 + 1) * 2) - 3 = 9console.log(result); // Output: 9
const trim = (str: string) => str.trim();const toUpperCase = (str: string) => str.toUpperCase();const exclaim = (str: string) => str + '!';
const composedString = useCompose(exclaim, toUpperCase, trim);const message = composedString(" hello world ");console.log(message); // Output: "HELLO WORLD!"
// Example 3: No-op (when no functions are provided)const identity = useCompose();console.log(identity(42)); // Output: 42
useCookie()
Section titled “useCookie()”The useCookie
hook is a simple utility to manage browser cookies.
It allows getting, setting, and deleting cookies in a straightforward way.
Functions Provided:
get
: Retrieves the value of the cookie by its name.set
: Sets a new value for the cookie with additional options (such as expiration or path).delete
: Deletes the cookie by setting a negativemax-age
.
Retrieving a Cookie
Section titled “Retrieving a Cookie”const { get } = useCookie('user-token');const token = get();console.log(token); // Prints the cookie value if exists, otherwise null
Setting a Cookie
Section titled “Setting a Cookie”const { set } = useCookie('user-token');set('abc123', { path: '/', expires: new Date(Date.now() + 3600 * 1000) }); // Expires in 1 hour
Deleting a Cookie
Section titled “Deleting a Cookie”const { delete: deleteCookie } = useCookie('user-token');deleteCookie();console.log(document.cookie); // The 'user-token' cookie is now deleted
useCurry()
Section titled “useCurry()”Hook for currying a function f(x, y, z) => f(x)(y)(z)
// Example 1: Basic curryingconst add = (x: number, y: number) => x + y;const curriedAdd = useCurry(add);console.log(curriedAdd(2)(3)); // Output: 5
// Example 2: String concatenationconst concat = (a: string, b: string, c: string) => a + b + c;const curriedConcat = useCurry(concat);console.log(curriedConcat('Hello')(' ')('World!')); // Output: "Hello World!"
// Example 3: No-op (when no arguments are provided)const noop = useCurry();console.log(noop()); // Output: undefined
useDebounce()
Section titled “useDebounce()”Hook for debouncing a function f(x) => useDebounce(f, 1000)(x)
// Example 1: Basic debouncingconst log = (message: string) => console.log(message);const debouncedLog = useDebounce(log, 1000);debouncedLog('Hello'); // Will log "Hello" after 1 second
// Example 2: Immediateconst immediateLog = useDebounce(log, 1000, { immediate: true });immediateLog('Immediate Hello'); // Will log "Immediate Hello" immediately
// Example 3: Canceling const cancelableLog = useDebounce(log, 1000); cancelableLog('Cancel me'); // Will log "Cancel me" after 1 second cancelableLog.cancel(); // Cancels the debounced function
// Example 4: No-op (when no arguments are provided)const noop = useDebounce();console.log(noop()); // Output: undefined
useEvent()
Section titled “useEvent()”The useEvent
hook is a utility for handling various events and mutations on DOM elements.
It allows you to specify an event type, a target element, and a callback function that will be executed when the event occurs.
Events
Section titled “Events”load
- Triggered when the element is loaded.viewport
- Triggered when the element enters or exits the viewport.attribute
- Triggered when an attribute of the element changes.children
- Triggered when the children of the element change.data
- Triggered when the data of the element changes.
export enum EVENTS { LOAD = 'load', VIEWPORT = 'viewport', ATTRIBUTE = 'attribute', CHILDREN = 'children', DATA = 'data',}
useEvent({ event: EVENTS.LOAD, target: '#myElement', effect: (el) => console.log('Element loaded:', el),});
useId()
Section titled “useId()”The hook useId
generates a unique ID associated with a given key, utilizing options for customization.
The IDs are stored internally to ensure they are reused unless forceNew
is set in the options
.
Params:
key
- A string or symbol or HTMLElement used to generate the ID.options
- Options to customize the generated ID. An object containing:prefix
- A string prefix for the ID.divider
- A string used to separate parts of the ID.forceNew
- A boolean indicating whether to force a new ID. Iftrue
, forces the generation of a new ID even if one already exists for the key.
// Generate an ID for a string keyconst id1 = useId("my-key");console.log(id1); // Outputs: "id-my_key-0" (depends on current counter)
// Generate an ID with customization optionsconst id2 = useId("customElement", { prefix: "custom", divider: "-", forceNew: true});// Outputs: "custom-customElement-0" (depends on current counter)console.log(id2);
// Reuse an existing ID for the same keyconst id1 = useId("my-key");const id3 = useId("my-key");console.log(id3 === id1); // true
// Generate IDs for different key typesconst id4 = useId(symbolKey);const id5 = useId(domElement);console.log(id4); // Example: "id-symbol-1"console.log(id5); // Example: "id-div-2"
useInterval()
Section titled “useInterval()”The useInterval
hook is a utility for creating and managing intervals in JavaScript.
const { start, stop } = useInterval(() => { console.log('Interval triggered');}, 1000);
start(); // Starts the intervalstop(); // Stops the interval
useMediaQuery()
Section titled “useMediaQuery()”useMediaQuery
- a custom hook that listens to changes in a specified media query and returns
whether the media query currently matches.
// Check if the viewport width is 600px or lessconst isSmallScreen = useMediaQuery("(max-width: 600px)");console.log(isSmallScreen); // true or false depending on the screen size
// Check for a dark mode preferenceconst prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");console.log(prefersDarkMode); // true if user prefers dark mode
useMemo()
Section titled “useMemo()”useMemo
- a hook to memoize the result of a function, with an optional maximum cache size.
const add = (a: number, b: number): number => a + b;const memoizedAdd = useMemo(add, { maxSize: 3 });
// Memoized function callsconsole.log(memoizedAdd(1, 2)); // 3, computedconsole.log(memoizedAdd(1, 2)); // 3, from cache
// Clear the cachememoizedAdd.clearCache();console.log(memoizedAdd(1, 2)); // 3, computed again after cache clear
usePipe()
Section titled “usePipe()”usePipe
- creates a pipeline of functions where the output of one function is passed as the input to the next.
This utility supports 0
, 1
, 2
, or more
functions as input:
- If no functions are provided, it returns an identity function.
- If one function is provided, it returns that function.
- If two functions are provided, it optimizes the pipeline for two functions.
- For more than two functions, it chains all functions in order.
// Piping two functions: adding 1 and doubling the resultconst addOne = (x: number) => x + 1;const double = (x: number) => x * 2;const piped = usePipe(addOne, double);console.log(piped(2)); // Output: 6
// Using a function pipeline with stringsconst toUpperCase = (str: string) => str.toUpperCase();const appendExclamation = (str: string) => `${str}!`;const piped = usePipe(toUpperCase, appendExclamation);console.log(piped('hello')); // Output: 'HELLO!'
// With no functions passedconst piped = usePipe();console.log(piped('unchanged')); // Output: 'unchanged'
// Chaining multiple functionsconst increment = (x: number) => x + 1;const square = (x: number) => x * x;const half = (x: number) => x / 2;const piped = usePipe(increment, square, half);console.log(piped(2)); // Output: 4.5
useQueue()
Section titled “useQueue()”useQueue
- A utility hook for managing a queue of items.
Provides methods to add, remove, and inspect items in the queue.
The hook returns function Object() { [native code] }. The methods to interact with the queue:
enqueue(item: T): number
- Adds an item to the queue and returns the new size of the queue.dequeue(): T | undefined
- Removes and returns the item at the front of the queue. Returnsundefined
if the queue is empty.peek(): T | null
- Returns the item at the front of the queue without removing it. Returnsnull
if the queue is empty.size(): number
- Returns the number of items in the queue.isEmpty(): boolean
- Checks if the queue is empty and returns a boolean value.clear(): void
- Clears all items in the queue.
// Create a new queueconst { enqueue, dequeue, peek, size, isEmpty, clear } = useQueue<number>();
// Add items to the queueenqueue(1); // Queue: [1], returns 1enqueue(2); // Queue: [1, 2], returns 2
// Check the first itemconsole.log(peek()); // Output: 1
// Remove the first itemconsole.log(dequeue()); // Output: 1, Queue: [2]
// Check the size of the queueconsole.log(size()); // Output: 1
// Check if the queue is emptyconsole.log(isEmpty()); // Output: false
// Clear the queueclear(); // Queue: []console.log(isEmpty()); // Output: true
useState()
Section titled “useState()”useState
- A custom hook that manages state, similar to React’s useState.
It allows tracking of state values and processes an optional callback when the state changes.
Params:
initialValue
- The initial value of the state.onChange
- An optional callback function that is called when the state changes. It receives the new and old values as arguments.
const onStateChange = (newValue: number, oldValue: number) => { console.log(`State changed from ${oldValue} to ${newValue}`);};
const [count, setCount] = useState(0, onStateChange);
console.log(+count); // Logs: 0
setCount(5); // Logs: "State changed from 0 to 5"
setCount(prev => prev + 1); // Logs: "State changed from 5 to 6"console.log(+count); // Logs: 6
console.log(String(count)); // Logs: "6"
useThrottle()
Section titled “useThrottle()”useThrottle
- Creates a throttled version of a given function that limits its execution to at most once every wait
milliseconds.
Supports options to control whether the function executes on the leading and/or trailing edge of the timeout.
// Throttle a function that logs a messageconst throttledLog = useThrottle((message) => console.log(message), 1000, { leading: true });throttledLog("Hello"); // Logs "Hello" immediatelythrottledLog("World"); // Ignored, as it's within the 1000ms wait period
setTimeout(() => { throttledLog("Goodbye"); // Logs "Goodbye" after 1000ms}, 1500);
// Cancel pending executionconst throttledFn = useThrottle(() => console.log("Executed"), 2000);throttledFn();throttledFn.cancel(); // Prevents the execution of the trailing call
useToggle()
Section titled “useToggle()”useToggle
- A custom hook that provides a simple way to toggle a boolean state value.
It returns the current state and a function to toggle it.
// Basic usageconst toggle = useToggle();console.log(toggle.get()); // falsetoggle.toggle(); // truetoggle.set(false); // false
// Initialize with a custom starting valueconst toggle = useToggle(true);console.log(toggle.get()); // truetoggle.toggle(); // falsetoggle.set(true); // true