Hiding or showing a element with React is as simple as an if statement deciding whether to print it or not. However often you want to be able to animate the transition, so that it smoothly closes or opens. To avoid cluttering the various components with this animation logic, extract the logic into a hook:
/**
* Returns the variables needed to animate a open and close functionality via height
* @param {Boolean} isOpen: boolean is the element initially open
* @param {Number} duration: number duration in ms
*/
function useHeightAnimation(isOpen = false, duration = 350) {
const contentRef = React.useRef(); // Inner wrapper that keeps the height if the outer animated is closed
const [height, setHeight] = React.useState(isOpen ? 'auto' : 0);
const handleClick = () => {
const contentRect = contentRef.current.getBoundingClientRect();
// Set the height so the element has an initial height to transition from
setHeight(`${contentRect.height}px`);
// Set the new desired height, either 0px or full height from the innerRef
setTimeout(() => setHeight(height === 0 ? `${contentRect.height}px` : 0));
setTimeout(
() => {
if (height === 0) {
// Set the height to "auto" to prevent issues with resizing when fully opened
setHeight('auto');
}
},
duration,
height,
);
};
return { height, handleClick, contentRef };
}
The hook can be used like: