IT虾米网

javascript之React Hooks 滚动到元素

pengyingh 2025年12月25日 程序员 36 0

我希望使用 React 16.8.6 编写一个 React hook,它可以让我在单击导航项时滚动到特定的 HTML 元素部分。我有一个 Navigation 组件,它是页面上呈现的部分的同级组件。

此外,当页面滚动时,我想使用该 HTML 部分更新 App 的状态。

导航组件 JSX

<ul class="nav> 
   <li><a>Section 1</a></li> 
   <li><a>Section 2</a></li>           
</ul> 

应用程序级别组件主页中的部分

<section className="section-1">Section 1</section> 
<section className="section-2">Section 2</section> 

Hook

 
const [navItem, setNavItem] = React.useState(null); 
const sectionRef = React.useRef(null); 
 
// Scroll To Item 
useEffect(() => { 
    console.log(sectionRef.current); 
    if (sectionRef.current) { 
      sectionRef.current.scrollToItem(); 
    } 
}, []); 

请您参考如下方法:

如果您不介意使用 react-router-dom,那么您可以跟踪历史记录更改并通过 将滚动位置更新为 HTML 元素的 id >哈希历史更改。这种方法的优点是您不必使用状态,也不必使用引用,并且它可以在整个应用程序中扩展(无论元素位于应用程序树中的哪个位置,您都可以滚动到它们)。

工作示例:

https://fglet.codesandbox.io/ (演示)

https://codesandbox.io/s/fglet (来源 - 不幸的是,在codesandbox编辑器中不起作用)

<小时 />

components/ScrollHandler(监听哈希历史记录更改的钩子(Hook),搜索与哈希中的 id 匹配的元素,如果找到匹配的元素 id,则它将滚动到元素)

import { useEffect } from "react"; 
import PropTypes from "prop-types"; 
import { withRouter } from "react-router-dom"; 
 
const ScrollHandler = ({ location }) => { 
  useEffect(() => { 
    const element = document.getElementById(location.hash)); 
 
    setTimeout(() => { 
      window.scrollTo({ 
        behavior: element ? "smooth" : "auto", 
        top: element ? element.offsetTop : 0 
      }); 
    }, 100); 
  }, [location]); 
 
  return null; 
}; 
 
ScrollHandler.propTypes = { 
  location: PropTypes.shape({ 
    pathname: PropTypes.string, 
    search: PropTypes.string, 
    hash: PropTypes.string, 
    state: PropTypes.any, 
    key: PropTypes.string 
  }).isRequired 
}; 
 
export default withRouter(ScrollHandler); 

组件/导航(更改 URL 哈希历史位置的链接)

import React from "react"; 
import { Link } from "react-router-dom"; 
import List from "../List"; 
 
const Navigation = () => ( 
  <List> 
    {[1, 2, 3, 4, 5].map(num => ( 
      <li key={num}> 
        <Link to={`/#section${num}`}>Section {num}</Link> 
      </li> 
    ))} 
  </List> 
); 
 
export default Navigation; 

组件/部分(Headline 组件包含要匹配的 id)

import React from "react"; 
import Headline from "../Headline"; 
 
const Sections = () => 
  [1, 2, 3, 4, 5].map(num => ( 
    <Headline key={num} id={`#section${num}`}> 
      Section {num} 
    </Headline> 
  )); 
 
export default Sections; 

index.js

import React from "react"; 
import { render } from "react-dom"; 
import { BrowserRouter } from "react-router-dom"; 
 
import Container from "./components/Container"; 
import Navigation from "./components/Navigation"; 
import Sections from "./components/Sections"; 
import ScrollHandler from "./components/ScrollHandler"; 
import "./styles.css"; 
 
const App = () => ( 
  <BrowserRouter> 
    <Container> 
      <ScrollHandler /> 
      <Navigation /> 
      <Sections /> 
    </Container> 
  </BrowserRouter> 
); 
 
render(<App />, document.getElementById("root")); 


评论关闭
IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!