mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-01 03:08:17 +02:00
perf(v2): reduce amount of navbar renders while scrolling (#4473)
This commit is contained in:
parent
af840b7f85
commit
f12e8b596d
4 changed files with 17 additions and 23 deletions
|
@ -190,12 +190,15 @@ function DocSidebar({
|
||||||
isHidden,
|
isHidden,
|
||||||
}: Props): JSX.Element | null {
|
}: Props): JSX.Element | null {
|
||||||
const [showResponsiveSidebar, setShowResponsiveSidebar] = useState(false);
|
const [showResponsiveSidebar, setShowResponsiveSidebar] = useState(false);
|
||||||
|
const [showAnnouncementBar, setShowAnnouncementBar] = useState(true);
|
||||||
const {
|
const {
|
||||||
navbar: {hideOnScroll},
|
navbar: {hideOnScroll},
|
||||||
hideableSidebar,
|
hideableSidebar,
|
||||||
} = useThemeConfig();
|
} = useThemeConfig();
|
||||||
const {isAnnouncementBarClosed} = useUserPreferencesContext();
|
const {isAnnouncementBarClosed} = useUserPreferencesContext();
|
||||||
const {scrollY} = useScrollPosition();
|
useScrollPosition(({scrollY}) => {
|
||||||
|
setShowAnnouncementBar(scrollY === 0);
|
||||||
|
});
|
||||||
|
|
||||||
useLockBodyScroll(showResponsiveSidebar);
|
useLockBodyScroll(showResponsiveSidebar);
|
||||||
const windowSize = useWindowSize();
|
const windowSize = useWindowSize();
|
||||||
|
@ -222,7 +225,7 @@ function DocSidebar({
|
||||||
{
|
{
|
||||||
'menu--show': showResponsiveSidebar,
|
'menu--show': showResponsiveSidebar,
|
||||||
[styles.menuWithAnnouncementBar]:
|
[styles.menuWithAnnouncementBar]:
|
||||||
!isAnnouncementBarClosed && scrollY === 0,
|
!isAnnouncementBarClosed && showAnnouncementBar,
|
||||||
},
|
},
|
||||||
)}>
|
)}>
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -14,7 +14,6 @@ const useHideableNavbar = (hideOnScroll: boolean): useHideableNavbarReturns => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const [isNavbarVisible, setIsNavbarVisible] = useState(hideOnScroll);
|
const [isNavbarVisible, setIsNavbarVisible] = useState(hideOnScroll);
|
||||||
const isFocusedAnchor = useRef(false);
|
const isFocusedAnchor = useRef(false);
|
||||||
const [lastScrollTop, setLastScrollTop] = useState(0);
|
|
||||||
const [navbarHeight, setNavbarHeight] = useState(0);
|
const [navbarHeight, setNavbarHeight] = useState(0);
|
||||||
const navbarRef = useCallback((node: HTMLElement | null) => {
|
const navbarRef = useCallback((node: HTMLElement | null) => {
|
||||||
if (node !== null) {
|
if (node !== null) {
|
||||||
|
@ -23,7 +22,7 @@ const useHideableNavbar = (hideOnScroll: boolean): useHideableNavbarReturns => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useScrollPosition(
|
useScrollPosition(
|
||||||
({scrollY: scrollTop}) => {
|
({scrollY: scrollTop}, {scrollY: lastScrollTop}) => {
|
||||||
if (!hideOnScroll) {
|
if (!hideOnScroll) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +35,6 @@ const useHideableNavbar = (hideOnScroll: boolean): useHideableNavbarReturns => {
|
||||||
if (isFocusedAnchor.current) {
|
if (isFocusedAnchor.current) {
|
||||||
isFocusedAnchor.current = false;
|
isFocusedAnchor.current = false;
|
||||||
setIsNavbarVisible(false);
|
setIsNavbarVisible(false);
|
||||||
setLastScrollTop(scrollTop);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,10 +51,8 @@ const useHideableNavbar = (hideOnScroll: boolean): useHideableNavbarReturns => {
|
||||||
} else if (scrollTop + windowHeight < documentHeight) {
|
} else if (scrollTop + windowHeight < documentHeight) {
|
||||||
setIsNavbarVisible(true);
|
setIsNavbarVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
setLastScrollTop(scrollTop);
|
|
||||||
},
|
},
|
||||||
[lastScrollTop, navbarHeight, isFocusedAnchor],
|
[navbarHeight, isFocusedAnchor],
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -64,10 +60,6 @@ const useHideableNavbar = (hideOnScroll: boolean): useHideableNavbarReturns => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lastScrollTop) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsNavbarVisible(true);
|
setIsNavbarVisible(true);
|
||||||
}, [location.pathname]);
|
}, [location.pathname]);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {useState, useEffect} from 'react';
|
import {useEffect, useRef} from 'react';
|
||||||
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
||||||
import type {ScrollPosition} from '@theme/hooks/useScrollPosition';
|
import type {ScrollPosition} from '@theme/hooks/useScrollPosition';
|
||||||
|
|
||||||
|
@ -15,19 +15,19 @@ const getScrollPosition = (): ScrollPosition => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const useScrollPosition = (
|
const useScrollPosition = (
|
||||||
effect?: (position: ScrollPosition) => void,
|
effect?: (position: ScrollPosition, lastPosition: ScrollPosition) => void,
|
||||||
deps = [],
|
deps = [],
|
||||||
): ScrollPosition => {
|
): void => {
|
||||||
const [scrollPosition, setScrollPosition] = useState(getScrollPosition());
|
const scrollPosition = useRef(getScrollPosition());
|
||||||
|
|
||||||
const handleScroll = () => {
|
const handleScroll = () => {
|
||||||
const currentScrollPosition = getScrollPosition();
|
const currentScrollPosition = getScrollPosition();
|
||||||
|
|
||||||
setScrollPosition(currentScrollPosition);
|
|
||||||
|
|
||||||
if (effect) {
|
if (effect) {
|
||||||
effect(currentScrollPosition);
|
effect(currentScrollPosition, scrollPosition.current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scrollPosition.current = currentScrollPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -35,12 +35,11 @@ const useScrollPosition = (
|
||||||
passive: true,
|
passive: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleScroll();
|
||||||
window.addEventListener('scroll', handleScroll, opts);
|
window.addEventListener('scroll', handleScroll, opts);
|
||||||
|
|
||||||
return () => window.removeEventListener('scroll', handleScroll, opts);
|
return () => window.removeEventListener('scroll', handleScroll, opts);
|
||||||
}, deps);
|
}, deps);
|
||||||
|
|
||||||
return scrollPosition;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useScrollPosition;
|
export default useScrollPosition;
|
||||||
|
|
|
@ -163,9 +163,9 @@ declare module '@theme/hooks/useScrollPosition' {
|
||||||
export type ScrollPosition = {scrollX: number; scrollY: number};
|
export type ScrollPosition = {scrollX: number; scrollY: number};
|
||||||
|
|
||||||
const useScrollPosition: (
|
const useScrollPosition: (
|
||||||
effect?: (position: ScrollPosition) => void,
|
effect?: (position: ScrollPosition, lastPosition: ScrollPosition) => void,
|
||||||
deps?: unknown[],
|
deps?: unknown[],
|
||||||
) => ScrollPosition;
|
) => void;
|
||||||
export default useScrollPosition;
|
export default useScrollPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue