perf(v2): reduce amount of navbar renders while scrolling (#4473)

This commit is contained in:
Armano 2021-03-22 19:32:11 +01:00 committed by GitHub
parent af840b7f85
commit f12e8b596d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 17 additions and 23 deletions

View file

@ -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

View file

@ -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]);

View file

@ -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;

View file

@ -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;
} }