@studio-lumio/hooks
Version:
a compilation of react hooks we use to make our magic
377 lines (272 loc) β’ 8.31 kB
Markdown
[]([hooks])
## Introduction
A collection of React hooks used at [Studio Lumio][lumio] to enhance our development workflow.
<br/>
π©The API may be changed without prior notice.
<br/>
## Setup
```bash
$ yarn add @studio-lumio/hooks
$ npm i @studio-lumio/hooks
```
<br/>
## Features
`useOnClickOutside` β Trigger a callback when the user clicks outside a reference node.
```
useOnClickOutside(ref, () => console.log('clicked outside'))
```
`useDebug` β returns true if #debug is present in the url.
```
const debug = useDebug()
```
`useDocumentReadyState` β returns true if document is ready.
```
const ready = useDocumentReadyState()
```
`useFrame` β runs callback on every frame
`useInterval` β create and dispose intervals.
```
useInterval(() => {
setCount(count + 1)
},1000)
// Delay in milliseconds or null to stop it
```
`useIsClient` β returns true if window is defined.
```
const isclient = useIsClient()
```
`useIsTouchDevice` β returns true if client is using a touch-capable device.
```
const isTouch = useIsTouchDevice()
```
`useIsVisible` β returns true if a reference node is in the viewport.
```
const { ref, inView } = useIsVisible({ threshold: 0.5, once: true, rootMargin: '0px', root: null })
```
`useMediaQuery` β css-like media query support in Javascript.
```
const match = useMediaQuery('(min-width: 1024px)')
```
`useRect` β Get getBoundingClientRect.
```
const { top, bottom } = useRect(elRef)
```
`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>
);
```
`useFoucFix` β temporary fix for FOUC bug from Next js
`useWindowSize` β returns window dimensions
```
const { width, height } = useWindowSize()
```
`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>;
};
```
```
const entry = useIntersectionObserver(ref, {})
```
`useIsomorphicLayoutEffect` β identical to useEffect, but fires synchronously after all DOM mutations.
```
useIsomorphicLayoutEffect(() => {
console.log(useIsomorphicLayoutEffect)
}, [])
```
`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>
```
`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>
);
};
```
`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 />;
};
```
`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)
```
`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)
```
`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);
```
`useEffectOnce` β `useEffect` that's executed only one time, on mount.
```
useEffectOnce(() => {
console.log('Triggered only on mount')
})
```
`useUpdateEffect` β `useEffect` that ignores the first invocation (e.g. on mount)
```
useUpdateEffect(() => {
console.log('ignores on mount', data)
}, [data])
```
`useIsMounted` β it returns a callback that returns true if the component is mounted
```
const isMounted = useIsMounted()
```
`useFirstMountState` β it returns true if component is just mounted.
```
const isFirstMountState = useFirstMountState()
```
`useLocalStorage` β it is used similarly to the `useState` hook. It takes in 2 parameters, the key and the initial value.
```
const [value, setValue, removeValue] = useLocalStorage('valueKey', [])
```
`useSessionStorage` β pretty much the same as `useLocalStorage` just for session storage
```
const [value, setValue] = useSessionStorage('valueKey', [])
```
```
const [value, setValue] = useSessionStorage('valueKey', [])
```
```
const {isVisible} = useIOSToolbarState()
```
```
useScript(url)
```
```
useFavicon(url);
```
```
useKeySequence({ sequence: 'sequence', callback: () => console.log('yay') })
```
```
const idle = useIdle(5000);
```
```
useDocumentTitle('new title');
```
```
const orientation = useOrientation();
```
```
usePageLeave(() => {
console.log('come back')
});
```
```
const [value, updateCookie, deleteCookie] = useCookie(cookieName: string);
```
```
export default function App() {
const [ref, hovering] = useHover();
return (
<div ref={ref}>
IsHovering? {hovering ? "Yes" : "No"}
</div>
);
}
```
```
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()
}
```
<br/>
## Authors
- Etuk Josiah Benjamin ([@jobenetuk](https://twitter.com/jobenetuk)) β [Studio Lumio][lumio]
<br/>
## License
[MIT (c)](https://opensource.org/licenses/MIT) [Studio Lumio][lumio].
[def]: https://github.com/studiolumio/hooks
[lumio]: https://studiolumio.com