A collection of utility hooks to problems I've solved over the years.
Install dependencies
$ npm install
Run storybook:
$ npm run dev
- storybook will be running at
http://localhost:6006
Build storybook static files:
$ npm run storybook:build
Run unit tests:
$ npm run test
Run unit tests in watch mode:
$ npm run test:watch
Run linter check:
$ npm run lint:check
Run linter auto fix:
$ npm run lint:fix
Run prettier check:
$ npm run format:check
Run prettier write:
$ npm run format:write
Run production build:
$ npm run build
- useAsyncScript
- useBreakpoint
- useComposedRefs
- useControlledReducer
- useOutsideClick
- usePrevious
- useRect
- useSubscription
- useWindowWidth
- A stateful hook for asynchronously loading 3rd party scripts in the browser. For example reCAPTCHA or google maps.
const url = 'https://example.com/?default=true';
export function AsyncScriptExample(): JSX.Element | null {
const { loading, done } = useAsyncScript(url);
if (loading) {
return <>Loading...</>;
}
if (done) {
return <>Script complete</>;
}
if (error) {
return <>Script errored</>;
}
return null;
}
- A hook that returns the current breakpoint according to the browser's window size.
Example:
export function BreakpointExample(){
const breakpoint = useBreakpoint();
return (
<div>
<div>{`Current breakpoint is: ${breakpoint}`}</div>
</div>
);
}
- also supports a config to set custom breakpoints
export function CustomConfigExample(){
const config = {
xsmall: { end: 300 },
small: { start: 300, end: 500 },
large: { start: 500 },
};
const breakpoint = useBreakpoint(config);
return (
<div>
<div>{`Current breakpoint is: ${breakpoint}`}</div>
</div>
);
}
- A hook to combine multiple instances of a ref into 1 instance to pass to an element.
const ForwardedRefComponent = forwardRef<HTMLElement, PropsWithChildren<{}>>(
(props, forwardedRef) => {
const internalRef = useRef<HTMLDivElement | null>(null);
const ref = useComposedRefs(internalRef, forwardedRef);
return (
<div ref={ref}>
{props.children}
</div>
);
}
);
- a low level hook that utilizes inversion of control and allows you to define a default reducer, and also allows for consumer to override state changes, and state values through props. Useful if you want a state that could be controlled or uncontrolled depending on the consumer props being passed in.
See an example implementation of a headless select hook that utilizes this hook.
- A hook that will execute a callback when a click occurs outside of an element.
function OutsideClickExample(){
const callback = (): void => {
alert('Clicked outside of the button');
};
const ref = useOutsideClick(callback);
return (
<button ref={ref}>Click outside of me</button>
);
}
- A hook that will keep track of the previous state of a stateful value.
export function PreviousStateExample() {
const [count, setCount] = useState(0);
const previousState = usePrevious(count);
function increaseCount() {
setCount(prevState => prevState + 1);
}
function decreaseCount() {
setCount(prevState => {
const nextState = prevState - 1;
return nextState < 0 ? 0 : nextState;
});
}
return (
<div>
<button onClick={increaseCount}>Increase</button>
<button onClick={decreaseCount}>Decrease</button>
<div>
{`Counter: ${count}`}
<div>{`Previous count: ${previousState}`}</div>
</div>
</div>
);
}
- A hook that returns the current DOMRect measurements for a DOM element
function DOMRectExample(){
const ref = useRef<HTMLDivElement | null>(null);
const rect = useRect(ref);
console.log(rect);
return (
<div ref={ref}>
My DOMRect will be tracked
</div>
)
}
- a hook for subscribing to external data sources.
import { useMemo } from 'react';
import debounce from 'lodash.debounce';
import { useSubscription } from '../useSubscription/useSubscription';
export function useWindowWidth(): number {
const source = window;
const subscription = useMemo(
() => ({
getCurrentValue: () => source.innerWidth,
subscribe: (callback: any) => {
source.addEventListener('resize', debounce(callback, 300));
return () => source.removeEventListener('resize', callback);
},
}),
[source.innerWidth]
);
return useSubscription(subscription);
}
- A hook that returns the current width of the browser window.
export function WindowWidthExample() {
const width = useWindowWidth();
return <div>{`Window's width is ${width}px`}</div>;
}