Support scroll to text fragment (#4060)

This commit is contained in:
Greg Bergé
2026-02-26 16:00:12 +01:00
committed by GitHub
parent b3e9ff9839
commit ec28a7b686
@@ -6,16 +6,33 @@ import { useHash } from './useHash';
import { usePrevious } from './usePrevious';
/**
* Scroll the page to the hash or reset scroll to the top.
* Only triggered while navigating in the app, not for initial load.
* Handles scroll behavior when the URL hash changes during client-side navigation.
*
* - If a hash is present, scrolls smoothly to the corresponding element.
* - If the hash is removed, scrolls back to the top of the page.
*
* This hook only reacts to in-app navigations. It avoids interfering with:
* - The browser's native hash scrolling on initial load
* - Scroll-to-text fragments (which cannot be reliably detected)
*/
export function useScrollPage() {
const hash = useHash();
const previousHash = usePrevious(hash);
React.useEffect(() => {
// If there's no hash:
// - On initial load, `previousHash` is undefined.
// We do nothing to avoid overriding:
// • Native browser hash scrolling
// • Scroll-to-text fragments (undetectable)
if (previousHash === undefined) {
return;
}
if (hash) {
if (previousHash !== undefined && previousHash !== hash) {
// Only scroll if this is not the initial render
// and the hash actually changed.
if (previousHash !== hash) {
const element = document.getElementById(hash);
if (element) {
element.scrollIntoView({
@@ -27,13 +44,8 @@ export function useScrollPage() {
return;
}
// On initial load `previousHash` can be undefined,
// but if the URL contains a fragment (hash),
// we don't override native anchor scrolling
if (!previousHash && window.location.hash) {
return;
}
// If the hash was removed during navigation,
// reset scroll position to the top.
window.scrollTo(0, 0);
}, [hash, previousHash]);
}