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

查看:1041
本文介绍了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,则可以跟踪历史记录更改,并通过id. >历史更改.这种方法的优点是您不必利用状态,也不必利用ref,它可以在整个应用程序中扩展(无论元素在应用程序树中的位置如何,您都可以滚动到它们).

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 (来源-不幸的是,没有在codeandbox编辑器中工作)

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

组件/导航(用于更改网址哈希历史记录位置的链接)

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;

组件/部分(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天全站免登陆