Я работаю над проектом React, где мне нужно, чтобы страница прокручивалась вверх при переходе на новый маршрут. Я реализовал компонент ScrollToTop
, но он, похоже, не работает. Страница сохраняет положение прокрутки после навигации.
Несмотря на реализацию компонента ScrollToTop
и проверку того, что console log
выводит правильные имена путей, страница не прокручивается вверх при изменении маршрута. Предыдущее положение прокрутки сохраняется.
console.info
в ScrollToTop.js работает и записывает правильные пути.ScrollToTop
включен в App.js
и обертывает Routes
.Код можно найти в моем репозитории GitHub
Я реализовал компонент ScrollToTop
, который использует хук useEffect для прокрутки вверх страницы при изменении пути. Я ожидал, что этот компонент будет сбрасывать позицию прокрутки в верхнюю часть страницы при каждом изменении маршрута.
Однако, несмотря на правильное размещение компонента и регистрацию изменений имени пути, страница по-прежнему сохраняет предыдущую позицию прокрутки после навигации, что не является предполагаемым поведением.
Я также хочу сказать, что я прочитал все соответствующие сообщения по этому вопросу в Stack Overflow, и, похоже, мне ничего не помогло. Я перепробовал все ресурсы, чтобы попытаться решить эту проблему.
Ответы на другие вопросы не работают в моем сценарии.
Приложение.js:
import React, { useState, useRef } from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import NavBar from "./components/NavBar.js";
import Contact from "./components/Contact.js";
import Widgets from "./components/widgets/Widgets.js";
import Footer from "./components/Footer.js";
import Currency from "./components/widgets/Currency.js";
import Timer from "./components/widgets/Timer.js";
import Weather from "./components/widgets/Weather.js";
import MainPage from "./components/MainPage.js";
import ScrollToTop from "./components/ScrollToTop.js";
function App() {
const [isSidebarVisible, setIsSidebarVisible] = useState(true);
const toggleSidebar = () => setIsSidebarVisible(!isSidebarVisible);
const personalRef = useRef(null);
const skillsRef = useRef(null);
const workRef = useRef(null);
const educationRef = useRef(null);
const publicationsRef = useRef(null);
const refs = {
personal: personalRef,
skills: skillsRef,
work: workRef,
education: educationRef,
publications: publicationsRef,
};
return (
<Router>
<ScrollToTop />
<div className = "flex min-h-screen overflow-hidden">
<NavBar
isSidebarVisible = {isSidebarVisible}
toggleSidebar = {toggleSidebar}
refs = {refs}
/>
<div
className = {`flex-1 flex flex-col transition-all duration-300 ${
isSidebarVisible ? "ml-20" : "ml-0"
}`}
>
<header className = "flex justify-between items-center p-8 bg-gray-800 text-white fixed w-full top-0 left-0 z-30 transition-all duration-300">
<h1
className = {`text-2xl transition-all duration-300 ${
isSidebarVisible ? "ml-20" : "ml-0"
}`}
>
Richard Lechko - IT Student @ DePaul University
</h1>
<button
onClick = {toggleSidebar}
className = "p-2 bg-blue-500 text-white rounded"
>
{isSidebarVisible ? "Close Sidebar" : "Open Sidebar"}
</button>
</header>
<main className = "flex-1 flex flex-col pt-24 overflow-hidden">
<Routes>
<Route
path = "/"
element = {
<MainPage
personalRef = {personalRef}
skillsRef = {skillsRef}
workRef = {workRef}
educationRef = {educationRef}
publicationsRef = {publicationsRef}
/>
}
/>
<Route path = "/contact" element = {<Contact />} />
<Route path = "/widgets" element = {<Widgets />} />
<Route path = "/widgets/currency" element = {<Currency />} />
<Route path = "/widgets/timer" element = {<Timer />} />
<Route path = "/widgets/weather" element = {<Weather />} />
</Routes>
<Footer refs = {refs} />
</main>
</div>
</div>
</Router>
);
}
export default App;
ПрокруткаToTop.js:
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
const ScrollToTop = () => {
const { pathname } = useLocation();
useEffect(() => {
console.info('ScrollToTop: Pathname changed to', pathname);
setTimeout(() => {
window.scrollTo(0, 0);
}, 0);
}, [pathname]);
return null;
};
export default ScrollToTop;
NavBar.js:
import React, { useEffect } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import {
FaUser,
FaTools,
FaBriefcase,
FaGraduationCap,
FaBook,
FaEnvelope,
} from "react-icons/fa";
const NavBar = ({ isSidebarVisible, refs, toggleSidebar }) => {
const navigate = useNavigate();
const location = useLocation();
const handleNavClick = (sectionId) => {
if (refs[sectionId] && refs[sectionId].current) {
refs[sectionId].current.scrollIntoView({ behavior: "smooth" });
} else {
navigate("/");
setTimeout(() => {
if (refs[sectionId] && refs[sectionId].current) {
refs[sectionId].current.scrollIntoView({ behavior: "smooth" });
}
}, 100);
}
};
const handleExternalNavClick = (path) => {
navigate(path, { replace: true });
};
useEffect(() => {
window.scrollTo(0, 0);
}, [location.pathname]);
return (
<div
className = {`fixed top-0 h-screen ${
isSidebarVisible ? "w-20" : "w-0"
} bg-gray-900 text-white shadow-lg transition-all duration-300 z-40`}
>
<nav>
<ul>
<NavItem icon = {<FaUser size = {28} />} onClick = {() => handleNavClick('personal')} />
<NavItem icon = {<FaTools size = {28} />} onClick = {() => handleNavClick('skills')} />
<NavItem icon = {<FaBriefcase size = {28} />} onClick = {() => handleNavClick('work')} />
<NavItem icon = {<FaGraduationCap size = {28} />} onClick = {() => handleNavClick('education')} />
<NavItem icon = {<FaBook size = {28} />} onClick = {() => handleNavClick('publications')} />
<NavItem icon = {<FaEnvelope size = {28} />} onClick = {() => handleExternalNavClick('/contact')} />
<NavItem icon = {<FaTools size = {28} />} onClick = {() => handleExternalNavClick('/widgets')} />
</ul>
</nav>
</div>
);
};
const NavItem = ({ icon, onClick }) => {
return (
<li onClick = {onClick}>
<div className = "flex justify-center items-center p-4 hover:bg-gray-700 transition-colors cursor-pointer">
{icon}
</div>
</li>
);
};
export default NavBar;
window.scrollTo(0,0)
недействителен, потому что само окно вашего окна не может прокручиваться, попробуйте window.document.body.scrollTo(0,0)
Спасибо, это очень помогло!