From 2d89d5c84f95df927aca03557e50a2fd3e7ed02d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 15 Apr 2021 18:43:38 +0200 Subject: [PATCH] refactor(v2): simplify and optimize sidebar (#4617) * safe sidebar refactor * simplify and optimize a bit the sidebar code --- .../src/theme/DocSidebar/index.tsx | 262 ++++++++++-------- 1 file changed, 151 insertions(+), 111 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.tsx index 6c5c9f7b46a2..9842fd52d44b 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.tsx @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import React, {useState, useCallback, useEffect, useRef, useMemo} from 'react'; +import React, {useState, useCallback, useEffect, useRef, memo} from 'react'; import clsx from 'clsx'; import {useThemeConfig, isSamePath} from '@docusaurus/theme-common'; import useUserPreferencesContext from '@theme/hooks/useUserPreferencesContext'; @@ -44,6 +44,32 @@ const isActiveSidebarItem = (item, activePath) => { return false; }; +// Optimize sidebar at each "level" +// TODO this item should probably not receive the "activePath" props +// TODO this triggers whole sidebar re-renders on navigation +const DocSidebarItems = memo(function DocSidebarItems({ + items, + ...props +}: any): JSX.Element { + return items.map((item, index) => ( + + )); +}); + +function DocSidebarItem(props): JSX.Element { + switch (props.item.type) { + case 'category': + return ; + case 'link': + default: + return ; + } +} + function DocSidebarItemCategory({ item, onItemClick, @@ -104,8 +130,7 @@ function DocSidebarItemCategory({
  • + })}> - {items.map((childItem) => ( - - ))} +
  • ); @@ -172,37 +194,24 @@ function DocSidebarItemLink({ ); } -function DocSidebarItem(props): JSX.Element { - switch (props.item.type) { - case 'category': - return ; - case 'link': - default: - return ; - } -} - -function DocSidebar({ - path, - sidebar, - sidebarCollapsible = true, - onCollapse, - isHidden, -}: Props): JSX.Element | null { - const [showResponsiveSidebar, setShowResponsiveSidebar] = useState(false); - const [showAnnouncementBar, setShowAnnouncementBar] = useState(true); - const { - navbar: {hideOnScroll}, - hideableSidebar, - } = useThemeConfig(); +function useShowAnnouncementBar() { const {isAnnouncementBarClosed} = useUserPreferencesContext(); + const [showAnnouncementBar, setShowAnnouncementBar] = useState( + !isAnnouncementBarClosed, + ); useScrollPosition(({scrollY}) => { - setShowAnnouncementBar(scrollY === 0); + if (!isAnnouncementBarClosed) { + setShowAnnouncementBar(scrollY === 0); + } }); + return showAnnouncementBar; +} +function useResponsiveSidebar() { + const [showResponsiveSidebar, setShowResponsiveSidebar] = useState(false); useLockBodyScroll(showResponsiveSidebar); - const windowSize = useWindowSize(); + const windowSize = useWindowSize(); useEffect(() => { if (windowSize === windowSizes.desktop) { setShowResponsiveSidebar(false); @@ -216,19 +225,99 @@ function DocSidebar({ }, [setShowResponsiveSidebar], ); - const sidebarItems = useMemo( - () => - sidebar.map((item) => ( - { + setShowResponsiveSidebar(!showResponsiveSidebar); + }, [setShowResponsiveSidebar]); + + return { + showResponsiveSidebar, + closeResponsiveSidebar, + toggleResponsiveSidebar, + }; +} + +function HideableSidebarButton({onClick}) { + return ( + + ); +} + +function ResponsiveSidebarButton({responsiveSidebarOpened, onClick}) { + return ( + ); +} + +function DocSidebar({ + path, + sidebar, + sidebarCollapsible = true, + onCollapse, + isHidden, +}: Props): JSX.Element | null { + const showAnnouncementBar = useShowAnnouncementBar(); + const { + navbar: {hideOnScroll}, + hideableSidebar, + } = useThemeConfig(); + const {isAnnouncementBarClosed} = useUserPreferencesContext(); + + const { + showResponsiveSidebar, + closeResponsiveSidebar, + toggleResponsiveSidebar, + } = useResponsiveSidebar(); return (
    - -
      {sidebarItems}
    + +
      + +
    - {hideableSidebar && ( - - )} + {hideableSidebar && } ); }