import React from "react"; export interface INavbarCollapseProps { children?: React.ReactNode | React.ReactNode[]; className?: string; isOpen: boolean; overflow?: string; } class NavbarCollapse extends React.PureComponent { private contentRef: React.RefObject; constructor(props: INavbarCollapseProps) { super(props); this.contentRef = React.createRef(); this.state = { height: props.isOpen ? "auto" : "0", overflow: this.props.overflow ? this.props.overflow : "hidden" }; } componentDidUpdate(prevProps: INavbarCollapseProps) { if ((this.props.isOpen && !prevProps.isOpen) || (!this.props.isOpen && prevProps.isOpen)) { this.setState({ height: `${this.getHeight()}px` }); } if (!this.props.isOpen && prevProps.isOpen) { window.requestAnimationFrame(() => { // "pausing" the JavaScript execution to let the rendering threads catch up // http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful setTimeout(() => { this.setState({ height: "0px" }); }); }); } } onTransitionEnd = (e: React.TransitionEvent) => { const { isOpen } = this.props; if (e && e.currentTarget === this.contentRef.current && e.propertyName === "height") { if (isOpen) { this.setExpanded(); } } }; getHeight = () => { return this.contentRef.current?.scrollHeight; }; setExpanded = () => { this.setState({ height: "auto" }); }; render() { const { className, children, isOpen, ...props } = this.props; return (
{children}
); } } export default NavbarCollapse;