Introduction
A compilation of react hooks we use to make our magic at Studio Lumio, heavily inspired by the SFDR's Hamo
Setup
$ yarn add @studio-lumio/hooks
$ npm i @studio-lumio/hooks
Features
This toolkit is composed of:
- useOnClickOutside –
triggers a callback when user clicks outside of a reference node.
useOnClickOutside(ref, () => console.log('clicked outside'))
copy - useDebug –
returns true if #debug is present in the url.
const debug = useDebug()
copy - useDocumentReadyState –
returns true if document is ready.
const ready = useDocumentReadyState()
copy - useFrame –
runs callback on every frame
- useInterval –
create and dispose intervals.
useInterval(() => { setCount(count + 1) }, // Delay in milliseconds or null to stop it 1000)
copy - useIsClient –
returns true if window is defined.
const isclient = useIsClient()
copy - useIsTouchDevice –
returns true if client is using a touch-capable device.
const isTouch = useIsTouchDevice()
copy - useIsVisible –
returns true if a reference node is in the viewport.
const { ref, inView } = useIsVisible({ threshold: 0.5, once: true, rootMargin: '0px', root: null })
copy - useMediaQuery –
css-like media query support in Javascript.
const match = useMediaQuery('(min-width: 1024px)')
copy - useRect –
getboundingclientrect
const { top, bottom } = useRect(elRef)
copy - useSlots –
A React hook for extracting the children of specified component types from a component’s children.
Parameters • types (array): An array of component types to extract children from. Default: []. • children (array): The children from which to extract the specified component types. Default: []. Returns • An array of children of the specified component types. const Header = ({ children }) => <header>{children}</header>; const Footer = ({ children }) => <footer>{children}</footer>; const MyComponent = ({ children }) => { const [headerContent, footerContent] = useSlots([Header, Footer], children); return ( <div> <div className="header-content"> {headerContent || 'Default Header Content'} </div> <div className="footer-content"> {footerContent || 'Default Footer Content'} </div> </div> ); }; const App = () => ( <MyComponent> <Header>My Header</Header> <Footer>My Footer</Footer> </MyComponent> );
copy - useFoucFix –
temporary fix for FOUC bug from Next js
- useWindowSize –
returns window dimensions
const { width, height } = useWindowSize()
copy - useIntersectionObserver –
Observe element visibility using IntersectionObserver
Parameters • root (HTMLElement | null): Viewport for checking visibility. • rootMargin (string): Margin around the root. • threshold (number): Visibility threshold (0 to 1). • once (boolean): Disconnect after first intersection. • lazy (boolean): Update state lazily. • callback (function): Function called on visibility change. const App = () => { const [setElement, entry] = useIntersectionObserver({ threshold: 0.5 }); return <div ref={setElement}>Observe me</div>; };
copy - useIsomorphicLayoutEffect –
identical to useEffect, but fires synchronously after all DOM mutations.
useIsomorphicLayoutEffect(() => { console.log(useIsomorphicLayoutEffect) }, [])
copy - useCopyToClipboard –
provides a copy method to save a string in the clipboard and the copied value
const [value, copy] = useCopyToClipboard() const handleClick = () => { copy('copy me', callback) } <button onClick={handleClick}>Meh</button>
copy - useEventListener –
it does what the name says. Pass in an event and a callback function as the second parameter
const elRef = useRef<HTMLElement>(null) const documentRef = useRef<Document>(document) // for window based event useEventListener('scroll', () => console.log('scroll')) // for document based event useEventListener('visibilitychange', () => console.log('visibilitychange'), documentRef) // for element based event useEventListener('click', () => console.log('clicked'), elRef)
copy - useRealViewport –
Set CSS variables for viewport units on browsers.
CSS Variables • --vw: Viewport width. • --dvh: Dynamic viewport height. • --svh: Small viewport height. • --lvh: Logical viewport height (1vh). const App = () => { useRealViewport(); return <YourComponent />; };
copy - useResizeObserver –
A React hook for observing element dimensions using ResizeObserver, with optional debouncing and lazy state updates.
Parameters • lazy (boolean): If true, returns a getter for the current entry instead of state. Default: false. • debounce (number): Delay in ms between resize events. Default: 500. • box (string): Box model to observe ('border-box', 'content-box'). Default: 'border-box'. • callback (function): Called on resize with ResizeObserverEntry. Default: () => {}. const MyComponent = () => { const [setElement, entry] = useResizeObserver({ debounce: 300, callback: (entry) => { console.log('Resized:', entry); }, }); useEffect(() => { if (entry) { console.log('Current entry:', entry); } }, [entry]); return ( <div ref={setElement} style={{ resize: 'both', overflow: 'auto', width: 200, height: 200 }}> Resize me! </div> ); };
copy - useDebounce –
uses an internal timer to update the variable every x seconds (2nd parameter)
const [value, setValue] = useState<string>('') const debouncedValue = useDebounce<string>(value, 500)
copy - useDebounceFn –
uses an internal timer to execute the callback function every x seconds (2nd parameter)
const debouncedFn = useDebounceFn(() => { console.log('This function is debounced!'); }, 500);
copy - useEffectOnce –
useEffect that's executed only one time, on mount.
useEffectOnce(() => { console.log('Triggered only on mount') })
copy - useUpdateEffect –
useEffect that ignores the first invocation (e.g. on mount)
useUpdateEffect(() => { console.log('ignores on mount', data) }, [data])
copy - useIsMounted –
it returns a callback that returns true if the component is mounted
const isMounted = useIsMounted()
copy - useFirstMountState –
it returns true if component is just mounted.
const isFirstMountState = useFirstMountState()
copy - useLocalStorage –
it is used similarly to ths useState hook. It takes in 2 parameters, the key and the initial value.
const [value, setValue, removeValue] = useLocalStorage('valueKey', [])
copy - useSessionStorage –
pretty much the same as useLocalStorage just for session storage
const [value, setValue, removeValue] = useSessionStorage('valueKey', [])
copy - useScript –
Load and manage external JavaScript scripts with useScript.
useScript(url)
copy - useFavicon –
Dynamically update the favicon with useFavicon.
useFavicon(url);
copy - useKeySequence –
Detect and perform actions on key press sequence.
useKeySequence({ sequence: 'sequence', callback: () => console.log('yay') })
copy - useIdle –
Detect user inactivity with useIdle.
const idle = useIdle(5000);
copy - useDocumentTitle –
Dynamically update the title of a webpage with useDocumentTitle.
useDocumentTitle('new title')
copy - useOrientation –
Manage and respond to changes in device orientation with useOrientation.
const orientation = useOrientation();
copy - usePageLeave –
Track when a user navigates away from a webpage with usePageLeave.
usePageLeave(() => { console.log('come back') });
copy - useCookie –
React hook that returns the current value of a cookie, a callback to update the cookie and a callback to delete the cookie.
const [value, updateCookie, deleteCookie] = useCookie(cookieName: string);
copy - useList –
Manage and manipulate lists with useList.
const [list, { set, push, removeAt, insertAt, updateAt, clear }] = useList([ "one", "two", "three", ]); console.log(list) const random = () => { set([1, 2, 3]) push([1, 2, 3]) removeAt(1) insertAt(1, "okay") updateAt(1, "okay") clear() }
copy - useHover –
React hook that tracks if some element is being hovered by a mouse.
export default function App() { const [ref, hovering] = useHover(); return ( <div ref={ref}> IsHovering? {hovering ? "Yes" : "No"} </div> ); }
copy