React Hooks 滚动到元素 [英] React Hooks Scroll to Element

查看:59
本文介绍了React Hooks 滚动到元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am looking to write a React hook with React 16.8.6 that will let me scroll to a particular HTML element section on click of a navigation item. I have a Navigation component that is a sibling of the sections rendered on the page.

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

Also when the page scrolls, I would like to update state of the App with that HTML section.

<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>

钩子


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 通过 hash 历史更改.这种方法的优点是您不必使用状态,也不必使用引用,并且它可以在整个应用程序中扩展(无论元素位于应用程序树中的哪个位置,您都可以滚动到它们).

If you don't mind using react-router-dom, then you can track history changes and update the scroll position to an HTML element's id via a hash history change. The advantage of this approach is you don't have to utilize state, nor utilize refs, and it can scale across the entire application (regardless of where the elements are located within the application's tree, you can scroll to them).

工作示例:

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

https://codesandbox.io/s/fglet(来源——不幸的是,没有在代码和框编辑器中工作)

https://codesandbox.io/s/fglet (source -- unfortunately, doesn't work within the codesandbox editor)

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

components/ScrollHandler (hook that listens to hash history changes, searches for elements that match the id located within the hash and, if it finds a matching element id, then it'll scroll to the element)

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 哈希历史位置的链接)

components/Navigation (links to change url hash history location)

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;

components/Sections(Headline 组件包含将与之匹配的 id)

components/Sections (the Headline component contains the id that will be matched against)

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"));

这篇关于React Hooks 滚动到元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆