Custom Hooks
Reusable React hooks for common UI interactions and behaviors.
useAutoResizeTextarea
A hook that automatically adjusts textarea height based on content.
Import
import { useAutoResizeTextarea } from '../components/hooks/use-auto-resize-textarea';
Usage
function MyComponent() {
const { textareaRef, adjustHeight } = useAutoResizeTextarea({
minHeight: 44,
maxHeight: 200,
});
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
adjustHeight();
// Handle value change
};
return (
<textarea
ref={textareaRef}
onChange={handleChange}
placeholder="Type something..."
/>
);
}
Parameters
props
UseAutoResizeTextareaProps
required
Configuration object for the hookShow UseAutoResizeTextareaProps properties
Minimum height of the textarea in pixels
Maximum height of the textarea in pixels. If not provided, textarea can grow indefinitely
Returns
textareaRef
React.RefObject<HTMLTextAreaElement>
Ref object to attach to the textarea element
adjustHeight
(reset?: boolean) => void
Function to manually adjust the textarea heightIf true, resets the textarea to minHeight. Otherwise, calculates new height based on content
How It Works
- Initial Setup: Sets textarea height to
minHeight on mount
- Content-Based Sizing: When
adjustHeight() is called:
- Temporarily shrinks to
minHeight
- Measures
scrollHeight (actual content height)
- Sets height to content size, clamped between
minHeight and maxHeight
- Window Resize: Automatically adjusts on window resize events
Internal Implementation
const adjustHeight = useCallback(
(reset?: boolean) => {
const textarea = textareaRef.current;
if (!textarea) return;
if (reset) {
textarea.style.height = `${minHeight}px`;
return;
}
// Temporarily shrink to get the right scrollHeight
textarea.style.height = `${minHeight}px`;
// Calculate new height
const newHeight = Math.max(
minHeight,
Math.min(
textarea.scrollHeight,
maxHeight ?? Number.POSITIVE_INFINITY
)
);
textarea.style.height = `${newHeight}px`;
},
[minHeight, maxHeight]
);
Source Location
src/components/hooks/use-auto-resize-textarea.ts:8
useOutsideClick
A hook that detects clicks outside a specified element and triggers a callback.
Import
import { useOutsideClick } from '../components/hooks/use-outside-click';
Usage
import { useRef, useState } from 'react';
import { useOutsideClick } from '../components/hooks/use-outside-click';
function Dropdown() {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
useOutsideClick(dropdownRef, () => {
setIsOpen(false);
});
return (
<div ref={dropdownRef}>
<button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
{isOpen && (
<div className="dropdown-menu">
{/* Dropdown content */}
</div>
)}
</div>
);
}
Parameters
ref
React.RefObject<HTMLDivElement>
required
Reference to the element that should ignore outside clicks. Clicks on this element or its children will not trigger the callback.
Function to call when a click occurs outside the referenced elementcallback: (event: MouseEvent | TouchEvent) => void
Behavior
- Ignored Clicks: Clicks on the referenced element or any of its children do nothing
- Outside Clicks: Clicks anywhere else on the document trigger the callback
- Event Types: Listens to both
mousedown and touchstart events for mobile support
- Cleanup: Automatically removes event listeners on unmount
Implementation Details
useEffect(() => {
const listener = (event: any) => {
// DO NOTHING if clicking the target element or its children
if (!ref.current || ref.current.contains(event.target)) {
return;
}
callback(event);
};
document.addEventListener("mousedown", listener);
document.addEventListener("touchstart", listener);
return () => {
document.removeEventListener("mousedown", listener);
document.removeEventListener("touchstart", listener);
};
}, [ref, callback]);
Common Use Cases
- Closing dropdowns when clicking outside
- Dismissing modals
- Hiding tooltips or popovers
- Closing mobile menus
- Deactivating inline editors
Source Location
src/components/hooks/use-outside-click.tsx:3
Best Practices
useAutoResizeTextarea
- Always call
adjustHeight() in your onChange handler
- Set reasonable
minHeight and maxHeight values
- Consider UX: very tall textareas may be scrollable instead
useOutsideClick
- Ensure the ref is attached before the hook runs
- Memoize the callback with
useCallback to prevent unnecessary re-renders
- Be mindful of performance with many simultaneous outside click listeners
TypeScript Support
Both hooks are fully typed with TypeScript:
// useAutoResizeTextarea
interface UseAutoResizeTextareaProps {
minHeight: number;
maxHeight?: number;
}
// useOutsideClick
function useOutsideClick(
ref: React.RefObject<HTMLDivElement>,
callback: Function
): void