fix(v2): ignore hash changes in useChangeRoute hook (#5023)

* fix(v2): ignore hash changes in useChangeRoute hook

* refactor and introduce useLocationChange hook

Co-authored-by: slorber <lorber.sebastien@gmail.com>
This commit is contained in:
Alexey Pyltsyn 2021-06-22 13:41:58 +03:00 committed by GitHub
parent 41eaa690ee
commit 8bda3b2dbf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 73 additions and 37 deletions

View file

@ -167,6 +167,10 @@ declare module '@docusaurus/router' {
// eslint-disable-next-line import/no-extraneous-dependencies
export * from 'react-router-dom';
}
declare module '@docusaurus/history' {
// eslint-disable-next-line import/no-extraneous-dependencies
export * from 'history';
}
declare module '@docusaurus/useDocusaurusContext' {
export default function (): any;

View file

@ -7,7 +7,11 @@
import React, {useState, useCallback, useEffect, useRef, memo} from 'react';
import clsx from 'clsx';
import {useThemeConfig, isSamePath} from '@docusaurus/theme-common';
import {
useThemeConfig,
isSamePath,
usePrevious,
} from '@docusaurus/theme-common';
import useUserPreferencesContext from '@theme/hooks/useUserPreferencesContext';
import useLockBodyScroll from '@theme/hooks/useLockBodyScroll';
import useWindowSize, {windowSizes} from '@theme/hooks/useWindowSize';
@ -25,14 +29,6 @@ import styles from './styles.module.css';
const MOBILE_TOGGLE_SIZE = 24;
function usePrevious(value) {
const ref = useRef(value);
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
const isActiveSidebarItem = (item, activePath) => {
if (item.type === 'link') {
return isSamePath(item.href, activePath);

View file

@ -8,7 +8,7 @@
import React, {useRef} from 'react';
import clsx from 'clsx';
import Translate from '@docusaurus/Translate';
import {useChangeRoute} from '@docusaurus/theme-common';
import {useLocationChange} from '@docusaurus/theme-common';
import styles from './styles.module.css';
@ -32,8 +32,8 @@ function SkipToContent(): JSX.Element {
}
};
useChangeRoute(() => {
if (containerRef.current) {
useLocationChange(({location}) => {
if (containerRef.current && !location.hash) {
programmaticFocus(containerRef.current);
}
});

View file

@ -8,7 +8,7 @@
import {useState, useCallback, useEffect, useRef} from 'react';
import {useLocation} from '@docusaurus/router';
import useScrollPosition from '@theme/hooks/useScrollPosition';
import {useChangeRoute} from '@docusaurus/theme-common';
import {useLocationChange} from '@docusaurus/theme-common';
import type {useHideableNavbarReturns} from '@theme/hooks/useHideableNavbar';
const useHideableNavbar = (hideOnScroll: boolean): useHideableNavbarReturns => {
@ -56,8 +56,8 @@ const useHideableNavbar = (hideOnScroll: boolean): useHideableNavbarReturns => {
[navbarHeight, isFocusedAnchor],
);
useChangeRoute(() => {
if (!hideOnScroll) {
useLocationChange((locationChangeEvent) => {
if (!hideOnScroll || locationChangeEvent.location.hash) {
return;
}

View file

@ -33,7 +33,9 @@ export {useTitleFormatter} from './utils/generalUtils';
export {usePluralForm} from './utils/usePluralForm';
export {useChangeRoute} from './utils/useChangeRoute';
export {useLocationChange} from './utils/useLocationChange';
export {usePrevious} from './utils/usePrevious';
export {
useDocsPreferredVersion,

View file

@ -1,21 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {useRef, useEffect} from 'react';
import {useLocation} from '@docusaurus/router';
export function useChangeRoute(onRouteChange: () => void): void {
const {pathname} = useLocation();
const latestPathnameRef = useRef(pathname);
useEffect(() => {
if (pathname !== latestPathnameRef.current) {
latestPathnameRef.current = pathname;
onRouteChange();
}
}, [pathname, latestPathnameRef, onRouteChange]);
}

View file

@ -0,0 +1,37 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {useEffect, useRef} from 'react';
import {useLocation} from '@docusaurus/router';
import {Location} from '@docusaurus/history';
import {usePrevious} from './usePrevious';
type LocationChangeEvent = {
location: Location;
previousLocation: Location | undefined;
};
type OnLocationChange = (locationChangeEvent: LocationChangeEvent) => void;
export function useLocationChange(onLocationChange: OnLocationChange): void {
const location = useLocation();
const previousLocation = usePrevious(location);
const isFirst = useRef<boolean>(true);
useEffect(() => {
// Prevent first effect to trigger the listener on mount
if (isFirst.current) {
isFirst.current = false;
return;
}
onLocationChange({
location,
previousLocation,
});
}, [location]);
}

View file

@ -0,0 +1,18 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {useRef, useEffect} from 'react';
export function usePrevious<T>(value: T): T | undefined {
const ref = useRef<T>();
useEffect(() => {
ref.current = value;
});
return ref.current;
}