Skip to content Skip to sidebar Skip to footer

React Hooks Scroll To Element

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

Solution 1:

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

Working example:

https://fglet.codesandbox.io/ (demo)

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


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";
importPropTypesfrom"prop-types";
import { withRouter } from"react-router-dom";

constScrollHandler = ({ location }) => {
  useEffect(() => {
    const element = document.getElementById(location.hash));

    setTimeout(() => {
      window.scrollTo({
        behavior: element ? "smooth" : "auto",
        top: element ? element.offsetTop : 0
      });
    }, 100);
  }, [location]);

  returnnull;
};

ScrollHandler.propTypes = {
  location: PropTypes.shape({
    pathname: PropTypes.string,
    search: PropTypes.string,
    hash: PropTypes.string,
    state: PropTypes.any,
    key: PropTypes.string
  }).isRequired
};

exportdefaultwithRouter(ScrollHandler);

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

importReactfrom"react";
import { Link } from"react-router-dom";
importListfrom"../List";

constNavigation = () => (
  <List>
    {[1, 2, 3, 4, 5].map(num => (
      <likey={num}><Linkto={`/#section${num}`}>Section {num}</Link></li>
    ))}
  </List>
);

exportdefaultNavigation;

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

importReactfrom"react";
importHeadlinefrom"../Headline";

constSections = () =>
  [1, 2, 3, 4, 5].map(num => (
    <Headlinekey={num}id={`#section${num}`}>
      Section {num}
    </Headline>
  ));

exportdefaultSections;

index.js

importReactfrom"react";
import { render } from"react-dom";
import { BrowserRouter } from"react-router-dom";

importContainerfrom"./components/Container";
importNavigationfrom"./components/Navigation";
importSectionsfrom"./components/Sections";
importScrollHandlerfrom"./components/ScrollHandler";
import"./styles.css";

constApp = () => (
  <BrowserRouter><Container><ScrollHandler /><Navigation /><Sections /></Container></BrowserRouter>
);

render(<App />, document.getElementById("root"));

Post a Comment for "React Hooks Scroll To Element"