[英]How to fade in element on scroll using React Hooks/React Spring
[英]React Hooks Scroll to Element
我正在尋找使用 React 16.8.6 編寫一個 React 鈎子,它可以讓我在單擊導航項時滾動到特定的 HTML 元素部分。 我有一個Navigation
組件,它是頁面上呈現的部分的兄弟。
此外,當頁面滾動時,我想用 HTML 部分更新App
的 state。
<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
,那么您可以跟蹤歷史更改並通過hash
歷史更改將滾動位置更新為 HTML 元素的id
。 這種方法的優點是您不必使用狀態,也不必使用引用,並且它可以在整個應用程序中擴展(無論元素位於應用程序樹中的哪個位置,您都可以滾動到它們)。
工作示例:
https://fglet.codesandbox.io/ (演示)
https://codesandbox.io/s/fglet (來源——不幸的是,在codesandbox編輯器中不起作用)
components/ScrollHandler (偵聽哈希歷史更改的鈎子,搜索與位於哈希中的 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;
索引.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 路由器 V6。 有些事情沒有奏效,而且有所不同。 例如, withRouter
已被棄用。 如果您需要,React 路由器提供了一個解決方案( 鏈接)。
我的 V6 解決方案:
創建一個組件WithRouter.jsx
:
import { useLocation, useNavigate, useParams } from "react-router-dom";
function withRouter(Component) {
function ComponentWithRouterProp(props) {
let location = useLocation();
let navigate = useNavigate();
let params = useParams();
return <Component {...props} router={{ location, navigate, params }} />;
}
return ComponentWithRouterProp;
}
export default withRouter;
創建一個組件ScrollHandler.jsx
import { useEffect } from "react";
import WithRouter from "./WithRouter";
const ScrollHandler = ({ location }) => {
useEffect(() => {
const element = document.getElementById(location.hash.substring(1));
if (element) element.scrollIntoView();
}, [location]);
return null;
};
export default WithRouter(ScrollHandler);
在index.js
中,我將我的<App/>
組件與BrowserRouter as Router
包裝起來,如下所示:
<Router>
<App />
</Router>
然后在App.js
中,添加<ScrollHandler/>
組件:
<ScrollHandler location={location} />
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.