reactjs 滚动到每个转换的顶部react-router-dom v6

2wnc66cl  于 2023-01-08  发布在  React
关注(0)|答案(3)|浏览(239)

我试着用react-router dom v6在每一个页面变化的顶部滚动。代码只在我的主页上滚动,而不在我的角色详细信息页面上。我试过很多解决方案,但都不能让它们工作。我用“react-router-dom”:“^6.2.2”,
这是我迄今为止取得的成就:
ScrollToTop.js:

import { useEffect } from "react";
import { useLocation } from "react-router-dom";

export default function ScrollToTop({ children }) {
    const { pathname } = useLocation();
    
    useEffect(() => {
        window.scrollTo(0, 0);
    }, [pathname]);
    
    return children;
}

我的应用程序. js

<Router>
    <ScrollToTop>
      <Header />
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/character/:char_id" element={<CharacterDetail />} />
        <Route path='*' element={<PageNotFound />} />
      </Routes>
      <Footer />
    </ScrollToTop>
  </Router>

我也尝试过直接使用“window.scrollTo(0,0);“并通过滚动到我的useEffect中的一个ID而没有成功。感谢您的指导。

q3qa4bjr

q3qa4bjr1#

看来它也可以依赖于浏览器,一些浏览器开始处理“滚动恢复”由他们自己的(规格)。

import { useEffect } from "react";
import { useLocation } from "react-router-dom";

export default function ScrollToTop({ children }) {
  const { pathname } = useLocation();
  
  useEffect(() => {
    const canControlScrollRestoration = 'scrollRestoration' in window.history
    if (canControlScrollRestoration) {
      window.history.scrollRestoration = 'manual';
    }

    window.scrollTo(0, 0);
  }, [pathname]);
  
  return children;
}

附赠注解:我不会将children传递给这个组件,而是将它作为App的兄弟来呈现,这样,除非必要,否则当位置改变时,它不会触发重新呈现:

<Router>
  <ScrollToTop />
  <App />
</Router>
wbrvyc0a

wbrvyc0a2#

我发现,当你改变路由,屏幕显示总是保持不变的react路由器,所以它记住屏幕的位置,如果你记录窗口(console. log(window)),你会看到窗口位置总是0,0.=〉滚动到顶部的解决方案是行不通的.
我的解决方案是设置一个loading:true状态。当组件挂载时,setState loading:没错。
加载时:true =〉渲染一个空白组件
加载时:false =〉渲染主组件。
您的主要组件将安装从顶部,所以它将防止记住的位置React路由器。

const YourComponent = (props) =>{

   const [loading, setLoading] = useState(true);

   useEffect(()=>{
      setLoading(false)
   },[])

   if(loading){
      return(<BlankComponent/>)
   }else{
      return (<YourMainComponentDeatail/>)
   }

}
zed5wv10

zed5wv103#

可以尝试的一件事是将window.scrollTo函数包含在setTimeout函数中,延迟为0毫秒,如下所示:

useEffect(() => {
  setTimeout(() => {
    window.scrollTo(0, 0);
  }, 0);
}, [pathname]);

这将允许浏览器在滚动到顶部之前完成呈现新页面。
另一种选择是尝试使用useEffect钩子,并将空数组作为第二个参数,这样只会在组件挂载时运行一次效果,如下所示:

useEffect(() => {
  window.scrollTo(0, 0);
}, []);

这将确保在组件第一次呈现时页面总是滚动到顶部,而不管路径如何。

相关问题