问题描述
我正在寻找用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滚动到元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!