npm:utility-hooks | Skypack
You need to enable JavaScript to run this app.
Usage no npm install needed!
<script type="module">
import utilityHooks from 'https://cdn.skypack.dev/utility-hooks';
</script>
quot;
+ }
+ ]
}
Hooks
useEventCallback(callback)
Inspired by How to read an often-changing value from useCallback?
Unlike useCallback, useEventCallback does not accept second argument and stores original callback in ref.
function Form() {
const [text, updateText] = useState("");
- const textRef = useRef();
-
- useEffect(() => {
- textRef.current = text; // Write it to the ref
- });
-
- const handleSubmit = useCallback(() => {
- const currentText = textRef.current; // Read it from the ref
- alert(currentText);
- }, [textRef]); // Don't recreate handleSubmit like [text] would do
+ const handleSubmit = useEventCallback(() => {
+ alert(text);
+ });
return (
<>
<input value={text} onChange={e => updateText(e.target.value)} />
<ExpensiveTree onSubmit={handleSubmit} />
</>
);
}
useIsomorphicLayoutEffect(effect, deps)
Inspired by react-redux/src/utils/useIsomorphicLayoutEffect
Runs useLayoutEffect in browser environment (checks document.createElement), otherwise useEffect.
useConstant(factory)`
Inspired by How to create expensive objects lazily?
Runs factory only once and writes value in component ref.
function Image(props) {
- const ref = useRef(null);
const node = useRef();
-
- // ✅ IntersectionObserver is created lazily once
- function getObserver() {
- let observer = ref.current;
- if (observer !== null) {
- return observer;
- }
- let newObserver = new IntersectionObserver(onIntersect);
- ref.current = newObserver;
- return newObserver;
- }
+ const observer = useConstant(() => new IntersectionObserver(onIntersect));
useEffect(() => {
- getObserver().observe(node.current);
+ observer.observe(node.current);
}, [observer]);
}
useMemoWith(factory, deps, isEqual)
Inspired by Gist .
Compares each dependency with isEqual function to memoize value from factory.
export function useFetch(url, options) {
- const cachedOptionsRef = useRef();
-
- if (
- !cachedOptionsRef.current ||
- !_.isEqual(options, cachedOptionsRef.current)
- ) {
- cachedOptionsRef.current = options;
- }
+ const cachedOptions = useMemoWith(() => options, [options], _.isEqual);
useEffect(() => {
// Perform fetch
- }, [url, cachedOptionsRef.current]);
+ }, [url, cachedOptions]);
}
usePrevious(value)
Inspired by How to get the previous props or state?
Stores value used in previous render.
function Counter() {
- const prevCountRef = useRef();
const [count, setCount] = useState(0);
-
- useEffect(() => {
- prevCountRef.current = count;
- });
+ const prevCount = usePrevious(count);
return (
<h1>
- Now: {count}, before: {prevCountRef.current}
+ Now: {count}, before: {prevCount}
</h1>
);
}
usePromise(factory, deps)
Handles loading of promises created by factory function.
const [filter, setFilter] = useState('')
- const [value, setValue] = useState();
- const [error, setError] = useState()
- useEffect(() => {
- const controller = new AbortController();
- const runEffect = async () => {
- try {
- const value = await fetch(
- "https://foo.bars/api?filter=" + filter,
- { signal: controller.signal }
- );
-
- setValue(value);
- } catch (error) {
- if (err.name === 'AbortError') {
- console.log("Request was canceled via controller.abort");
- return;
- }
-
- setError(error)
- }
- };
- runEffect();
- return () => controller.abort()
- }, [filter]);
+ const { value, error } = usePromise(({ abortSignal }) => fetch(
+ "https://foo.bars/api?filter=" + filter,
+ { signal: abortSignal }
+ ), [filter])
usePureMemo(deps, isEqual)
Returns next deps only when they were changed based on isEqual result.
usePureMemo(factory, deps, isEqual)
Works like useMemoWith, but also compares return value.
export function useFetch(url, options) {
- const cachedOptionsRef = useRef();
-
- if (
- !cachedOptionsRef.current ||
- !_.isEqual(options, cachedOptionsRef.current)
- ) {
- cachedOptionsRef.current = options;
- }
+ const cachedOptions = usePureMemo(() => options, [options], _.isEqual);
useEffect(() => {
// Perform fetch
- }, [url, cachedOptionsRef.current]);
+ }, [url, cachedOptions]);
}
useValueRef(value)
Inspired by How to read an often-changing value from useCallback?
Works like useRef, but keeps it's ref in sync with value on every call.
function Form() {
const [text, updateText] = useState('');
+ const textRef = useValueRef(text);
- const textRef = useRef();
-
- useEffect(() => {
- textRef.current = text; // Write it to the ref
- });
const handleSubmit = useCallback(() => {
const currentText = textRef.current; // Read it from the ref
alert(currentText);
}, [textRef]); // Don't recreate handleSubmit like [text] would do
return (
<>
<input value={text} onChange={e => updateText(e.target.value)} />
<ExpensiveTree onSubmit={handleSubmit} />
</>
);
}
useWhenValueChanges(value, effect, isEqual)
Works like useEffect, but runs effect only when value compared by isEqual (Object.is if not provided). It also passes the previous value as an effect argument.
function List({ disptach, page, selectedId }) {
- const isInitial = useRef(true);
useEffect(() => {
- isInitial.current = true;
dispatch({ type: "FETCH_LIST", page });
}, [page, dispatch]);
useEffect(() => {
dispatch({ type: "FETCH_ITEM", id: selectedId });
}, [selectedId, dispatch]);
- useEffect(() => {
- if (isInitial.current) {
- isInitial.current = false;
- } else if (!selectedId) {
- dispatch({ type: "FETCH_LIST", page });
- }
- }, [page, selectedId, dispatch]);
+ useWhenValueChanges(selectedId, () => {
+ if (!selectedId) {
+ dispatch({ type: "FETCH_LIST", page });
+ }
+ });
}
Utilities
areDepsEqualWith(hookName, nextDeps, prevDeps, isEqual)
Compares each dependency with isEqual function.
Details
Updated
January 27, 2021
Created
March 19, 2019
Package Security
added
ES Module Entrypoint
Export Map
Info
Keywords
Info
added
License
added
README
added
Repository URL
added
TypeScript Types
License
MIT
Dependencies
0