Last active
October 26, 2022 14:06
-
-
Save zempo/a9a71f2a6d395b0a70d94b55bd1ab1aa to your computer and use it in GitHub Desktop.
My collection of custom React Hooks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
My ongoing collection of custom react hooks. | |
I always reference this snippet whenever starting a new react project. | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect } from "react"; | |
import { withRouter } from "react-router-dom"; | |
/* | |
USAGE | |
------------------------------ | |
import ScrollToTop from "./hooks/ScrollToTop"; | |
export const App = () => { | |
return ( | |
<> | |
<ScrollToTop /> | |
<main> | |
<Switch> | |
{Children...} | |
</Switch> | |
</main> | |
</> | |
) | |
} | |
------------------------- | |
* | |
*/ | |
function ScrollToTop({ history }) { | |
useEffect(() => { | |
const unlisten = history.listen(() => { | |
window.scrollTo(0, 0); | |
}); | |
return () => { | |
unlisten(); | |
}; | |
// eslint-disable-next-line react-hooks/exhaustive-deps | |
}, []); | |
return null; | |
} | |
export default withRouter(ScrollToTop); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState, useEffect } from "react"; | |
/* | |
* USAGE | |
--------------------------------- | |
export const myComponent = () => { | |
let height = useCurrentHeight(); | |
return ( | |
<> | |
{height} | |
</> | |
) | |
} | |
--------------------------------- | |
*/ | |
const getHeight = () => | |
window.innerHeight || | |
document.documentElement.clientHeight || | |
document.body.clientHeight; | |
export function useCurrentHeight() { | |
// save current window width in the state object | |
let [height, setHeight] = useState(getHeight()); | |
// in this case useEffect will execute only once because | |
// it does not have any dependencies. | |
useEffect(() => { | |
// timeoutId for debounce mechanism | |
let timeoutId = null; | |
const resizeListener = () => { | |
// prevent execution of previous setTimeout | |
clearTimeout(timeoutId); | |
// change height from the state object after 150 milliseconds | |
timeoutId = setTimeout(() => setHeight(getHeight()), 150); | |
}; | |
// set resize listener | |
window.addEventListener("resize", resizeListener); | |
// clean up function | |
return () => { | |
// remove resize listener | |
window.removeEventListener("resize", resizeListener); | |
}; | |
}, []); | |
return height; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState, useEffect } from "react"; | |
/* | |
* USAGE | |
--------------------------------- | |
export const myComponent = () => { | |
let width = useCurrentWidth(); | |
return ( | |
<> | |
{width} | |
</> | |
) | |
} | |
--------------------------------- | |
*/ | |
const getWidth = () => | |
window.innerWidth || | |
document.documentElement.clientWidth || | |
document.body.clientWidth; | |
export function useCurrentWidth() { | |
// save current window width in the state object | |
let [width, setWidth] = useState(getWidth()); | |
// in this case useEffect will execute only once because | |
// it does not have any dependencies. | |
useEffect(() => { | |
// timeoutId for debounce mechanism | |
let timeoutId = null; | |
const resizeListener = () => { | |
// prevent execution of previous setTimeout | |
clearTimeout(timeoutId); | |
// change width from the state object after 150 milliseconds | |
timeoutId = setTimeout(() => setWidth(getWidth()), 150); | |
}; | |
// set resize listener | |
window.addEventListener("resize", resizeListener); | |
// clean up function | |
return () => { | |
// remove resize listener | |
window.removeEventListener("resize", resizeListener); | |
}; | |
}, []); | |
return width; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useContext, useLayoutEffect, useRef, useState } from "react"; | |
/** | |
* Hook Creator: https://swizec.com/blog/usedimensions-a-react-hook-to-measure-dom-nodes/ | |
* GitHub: https://github.com/Swizec/useDimensions | |
* | |
* This hook has been modified to work on window resize | |
* | |
* USAGE | |
---------------------------- | |
export const myComponent = () => { | |
const [elRef, elSize] = useDimensions(); | |
return ( | |
<> | |
<div ref={elRef}> | |
{elSize} | |
</div> | |
</> | |
) | |
} | |
---------------------------- | |
* | |
*/ | |
export const useDimensions = () => { | |
const ref = useRef(); | |
const [dimensions, setDimensions] = useState({}); | |
useLayoutEffect(() => { | |
function handleResize() { | |
setDimensions(ref.current.getBoundingClientRect().toJSON()); | |
} | |
// call on mount | |
handleResize(); | |
window.addEventListener("resize", handleResize); | |
return () => window.removeEventListener("resize", handleResize); | |
// eslint-disable-next-line react-hooks/exhaustive-deps | |
}, [ref.current]); | |
return [ref, dimensions]; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState } from "react"; | |
/* | |
* USAGE | |
---------------------------- index.html | |
<div id="root"></div> | |
<div id="modal"></div> | |
---------------------------- | |
---------------------------- Modal.js | |
import React from "react"; | |
import ReactDOM from "react-dom"; | |
export const Modal = ({isShowing, hide}) => { | |
if (isShowing) { | |
return ReactDOM.createPortal( | |
<div onClick={hide} className='Modal'> | |
<div | |
onClick={(e) => e.stopPropagation()} | |
className={`Modal__inner ${isShowing}`} | |
> | |
</div> | |
</div>, | |
document.querySelector("#modal") | |
); | |
} else { | |
return null; | |
} | |
} | |
---------------------------- | |
---------------------------- MyComponent.js | |
export const myComponent = () => { | |
const { isShowing: isShowingItem, toggle: toggleItem } = | |
useModal(); | |
const openItem = () => { | |
toggleItem(); | |
}; | |
return ( | |
<> | |
<div> | |
<button className={`open-item`} onClick={openItem}> | |
<span>See More</span> | |
</button> | |
</div> | |
<Modal | |
isShowing={isShowingItem} | |
hide={toggleItem} | |
/> | |
</> | |
) | |
} | |
---------------------------- | |
*/ | |
export const useModal = () => { | |
const [isShowing, setIsShowing] = useState(false); | |
function toggle() { | |
setIsShowing(!isShowing); | |
} | |
return { | |
isShowing, | |
toggle, | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useDrag } from "react-use-gesture"; | |
/** | |
* HOOK CREDITS | |
* ------------- | |
* | |
* @WilliamIPark | |
* https://codesandbox.io/s/w77ui?file=/src/index.js | |
*/ | |
const anonFn = () => {}; | |
export default function useSwipe( | |
actions = { | |
onUp: anonFn, | |
onDown: anonFn, | |
onLeft: anonFn, | |
onRight: anonFn, | |
}, | |
threshold = 0.3 | |
) { | |
const bind = useDrag(({ last, vxvy: [vx, vy] }) => { | |
if (Math.abs(vx) > Math.abs(vy)) { | |
if (vx < -threshold && last) { | |
actions.onLeft(); | |
} else if (vx > threshold && last) { | |
actions.onRight(); | |
} | |
} else { | |
if (vy < -threshold && last) { | |
actions.onUp(); | |
} else if (vy > threshold && last) { | |
actions.onDown(); | |
} | |
} | |
}); | |
return bind; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment