diff --git a/src/NavbarOffcanvas.tsx b/src/NavbarOffcanvas.tsx index 05c6110428..dee2c4c8fc 100644 --- a/src/NavbarOffcanvas.tsx +++ b/src/NavbarOffcanvas.tsx @@ -9,7 +9,14 @@ const NavbarOffcanvas = React.forwardRef( (props, ref) => { const context = useContext(NavbarContext); - return ; + return ( + + ); }, ); diff --git a/src/Offcanvas.tsx b/src/Offcanvas.tsx index 37baf71cc9..2eae124c6d 100644 --- a/src/Offcanvas.tsx +++ b/src/Offcanvas.tsx @@ -45,6 +45,7 @@ export interface OffcanvasProps scroll?: boolean; placement?: OffcanvasPlacement; responsive?: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | string; + renderStaticNode?: boolean; } const propTypes = { @@ -176,6 +177,13 @@ const propTypes = { */ container: PropTypes.any, + /** + * For internal use to render static node from NavbarOffcanvas. + * + * @private + */ + renderStaticNode: PropTypes.bool, + 'aria-labelledby': PropTypes.string, }; @@ -188,6 +196,7 @@ const defaultProps: Partial = { enforceFocus: true, restoreFocus: true, placement: 'start', + renderStaticNode: false, }; function DialogTransition(props) { @@ -231,6 +240,7 @@ const Offcanvas: BsPrefixRefForwardingComponent<'div', OffcanvasProps> = onExited, backdropClassName, manager: propsManager, + renderStaticNode, ...props }, ref, @@ -317,9 +327,14 @@ const Offcanvas: BsPrefixRefForwardingComponent<'div', OffcanvasProps> = <> {/* Only render static elements when offcanvas isn't shown so we - don't duplicate elements + don't duplicate elements. + + TODO: Should follow bootstrap behavior and don't unmount children + when show={false} in BaseModal. Will do this next major version. */} - {!showOffcanvas && renderDialog({})} + {!showOffcanvas && + (responsive || renderStaticNode) && + renderDialog({})} ', () => { const offcanvasElem = getByTestId('test'); expect(offcanvasElem.getAttribute('role')).to.not.exist; }); + + it('should not mount, unmount and mount content on show', () => { + const InnerComponent = ({ onMount, onUnmount }) => { + useEffect(() => { + onMount(); + return () => { + onUnmount(); + }; + }, []); + + return
Content
; + }; + + const onMountSpy = sinon.spy(); + const onUnmountSpy = sinon.spy(); + + const { unmount } = render( + + + , + ); + + onMountSpy.callCount.should.equal(1); + + unmount(); + + onUnmountSpy.callCount.should.equal(1); + }); });