Skip to content

Instantly share code, notes, and snippets.

@rohailtaha
Last active June 28, 2024 11:06
Show Gist options
  • Save rohailtaha/b1731180c8b4dfaf88c91d507cbc1960 to your computer and use it in GitHub Desktop.
Save rohailtaha/b1731180c8b4dfaf88c91d507cbc1960 to your computer and use it in GitHub Desktop.
Custom Hooks and HOCS for React
export function useDocumentClickListener(eventListener) {
useEffect(() => {
document.addEventListener("click", eventListener)
return () => document.removeEventListener("click", eventListener)
}, [eventListener])
return null
}
import { useState } from 'react';
export default function useError() {
const initialState = {
error: false,
msg: '',
};
const [errorObj, setErrorObj] = useState(initialState);
const showError = (msg, duration = null) => {
setErrorObj({
error: true,
msg,
});
if (duration) {
setTimeout(hideError, duration);
}
};
const hideError = () => setErrorObj(initialState);
return [
{
...errorObj,
showError,
hideError,
},
];
}
export function useFormFeedback() {
const [formFeedback, setFormFeedback] = useState<FormFeedback | null>(null);
const setError = useCallback((message: string, interval?: number) => {
setFormFeedback({ type: 'error', message });
if (interval) {
setTimeout(() => {
setFormFeedback(null);
}, interval);
}
}, []);
const setSuccess = useCallback((message: string, interval?: number) => {
setFormFeedback({ type: 'success', message });
if (interval) {
setTimeout(() => {
setFormFeedback(null);
}, interval);
}
}, []);
const resetFeedback = useCallback(() => setFormFeedback(null), []);
return useMemo(
() => ({
formFeedback,
setError,
setSuccess,
resetFeedback,
}),
[formFeedback, resetFeedback, setError, setSuccess]
);
}
export function useIsMounted() {
const [mounted, setMounted] = useState(false)
useEffect(() => {
setMounted(true)
}, [])
return mounted
}
import React, { useState } from 'react';
function useLoader() {
const [loading, setLoading] = useState(false);
return [loading, setLoading];
}
export default useLoader;
export function useOutsideClickDetector({
cb,
ignoreDom,
}: {
cb: VoidFunction;
ignoreDom: MutableRefObject<HTMLElement | null>;
}) {
const handleClick = useCallback(
(e: MouseEvent) => {
if (!e.target) return;
if (
e.target === ignoreDom.current ||
ignoreDom.current?.contains(e.target as Node)
) {
return false;
} else {
cb();
}
},
[cb, ignoreDom]
);
useEffect(() => {
document.addEventListener('click', handleClick);
return () => {
document.removeEventListener('click', handleClick);
};
}, [handleClick]);
return null;
}
export function useToggler(initialState = false) {
const [state, setState] = useState(initialState)
function toggle() {
setState(prevState => !prevState)
}
return [state, toggle]
}
import { useOutsideClickDetector } from '@/hooks';
import { ComponentType, useRef } from 'react';
type WithLoggingProps = {
onClose: VoidFunction;
};
export function withOutsideClickDetector<T>(
WrappedComponent: ComponentType<T>
) {
return function Component(props: T & WithLoggingProps) {
const containerRef = useRef<null | HTMLDivElement>(null);
useOutsideClickDetector({ cb: props.onClose, ignoreDom: containerRef });
return (
<div ref={containerRef}>
<WrappedComponent {...props} />
</div>
);
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment