Skip to content

Instantly share code, notes, and snippets.

@nickdandakis
Last active September 15, 2020 20:41
Show Gist options
  • Save nickdandakis/2ede3938892a95504ed1171fe301c95c to your computer and use it in GitHub Desktop.
Save nickdandakis/2ede3938892a95504ed1171fe301c95c to your computer and use it in GitHub Desktop.
Common utility functions and hooks when working in a React codebase
export default function debounce (fn, delay) {
let timeoutID = null;
return function (...args) {
clearTimeout(timeoutID);
timeoutID = setTimeout(() => {
fn.call(this, ...args);
}, delay);
};
};
import React, { useRef } from 'react';
import useIsomorphicLayoutEffect from './useIsomorphicLayoutEffect';
function useAnimationFrame(callback) {
const callbackRef = useRef(callback);
useIsomorphicLayoutEffect(
() => {
callbackRef.current = callback;
},
[callback]
);
const loop = () => {
frameRef.current = requestAnimationFrame(loop);
const cb = callbackRef.current;
cb();
};
const frameRef = useRef();
useIsomorphicLayoutEffect(() => {
frameRef.current = requestAnimationFrame(loop);
return () => cancelAnimationFrame(frameRef.current);
}, []);
};
export default useAnimationFrame;
import React, { useEffect } from 'react';
function useClickOutside(
ref,
handler, // useCallback
) {
useEffect(
() => {
const listener = event => {
// Do nothing if clicking ref's element or descendent elements
if (!ref.current || ref.current.contains(event.target)) {
return;
}
handler(event);
};
document.addEventListener('mousedown', listener);
document.addEventListener('touchstart', listener);
return () => {
document.removeEventListener('mousedown', listener);
document.removeEventListener('touchstart', listener);
};
},
[ref, handler]
);
}
export default useClickOutside;
import { useCallback } from 'react';
import debounce from '../utils/debounce';
export const useDebouncedCallback = (func, duration = 200) => {
return useCallback(
debounce(func, duration)
, [func, duration]);
};
export default useDebouncedCallback;
import React, { useState, useEffect } from 'react';
function useDebouncedState(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(
() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
},
[value, delay] // Only re-call effect if value or delay changes
);
return debouncedValue;
}
export default useDebouncedState;
//https://fb.me/react-uselayouteffect-ssr
import React, { useEffect, useLayoutEffect } from 'react';
const useIsomorphicLayoutEffect = (
typeof window !== 'undefined'
? useLayoutEffect
: useEffect
);
export default useIsomorphicLayoutEffect;
import React, { useEffect } from 'react';
function useKeyDown(key, callback) {
useEffect(() => {
const handler = function(event) {
if (event.key === key) {
callback();
}
};
window.addEventListener('keydown', handler);
return () => {
window.removeEventListener('keydown', handler);
}
}, []);
}
export default useKeyDown;
import React, { useEffect, useState } from 'react';
function useWindowLoad() {
const [hasLoaded, setHasLoaded] = useState(false);
function handler () {
setHasLoaded(true);
}
useEffect(() => {
window.addEventListener('load', handler);
return () => {
window.removeEventListener('load', handler);
}
}, []);
return hasLoaded;
}
export default useWindowLoad;
import React, { useState } from 'react';
import useAnimationFrame from './useAnimationFrame';
function useWindowScrollPosition() {
const [position, setPosition] = useState({
x: 0,
y: 0,
});
useAnimationFrame(() => {
const x = window.pageXOffset;
const y = window.pageYOffset;
setPosition({
x,
y,
});
});
return position;
}
export default useWindowScrollPosition;
import React, { useState } from 'react';
import useAnimationFrame from './useAnimationFrame';
function useWindowSize() {
const [position, setPosition] = useState({
width: 0,
height: 0,
});
useAnimationFrame(() => {
const width = window.innerWidth;
const height = window.innerHeight;
setPosition({
width,
height,
});
});
return position;
}
export default useWindowSize;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment