React change view and then scroll to element
Asked Answered
E

3

5

I want to link from one view to another and then scroll to a specific element. I'm not intrested in any animations, only want to have the element in view. The link from one view to another is done through react router.

I guess I could somehow create references on the elements I want to scroll to and pass them to the other view, but don't know if that's the correct approach?

A simple example. (Not working, but hopefully you understand what I want to achieve)

const ViewOne = () => {
  const navigate = useNavigate(); // From react-router v6
  return (
    <p onClick={() => 
    {
      navigate("ViewTwo"); 
      // What more do I have to add? 
    }}>
      Link to section two, in view two
    </p>
  );
}

export default ViewOne;
const ViewTwo = () => {
return (
  <>
    <section style={{height: "100vh"}}></section>
    <section style={{height: "100vh"}}>
      Scroll here?
    </section>
    <section style={{height: "100vh"}}></section>
  </>);
}
export default ViewTwo;

I'm using react-router-dom-v6

Ermeena answered 22/4, 2022 at 21:40 Comment(0)
J
6

Give the sections you want to target and scroll to id attributes. Pass a target id in route state. Use a useEffect hook to target the element and scroll it into view.

Example:

const ViewOne = () => {
  const navigate = useNavigate(); // From react-router v6
  return (
    <p
      onClick={() => {
        navigate("/viewtwo", { state: { targetId: "section2" } });
      }}
    >
      Link to section two, in view two
    </p>
  );
};

...

const ViewTwo = () => {
  const { state } = useLocation();
  const { targetId } = state || {};

  useEffect(() => {
    const el = document.getElementById(targetId);
    if (el) {
      el.scrollIntoView();
    }
  }, [targetId]);

  return (
    <>
      <section id="section1" style={{ height: "100vh" }}></section>
      <section id="section2" style={{ height: "100vh" }}>
        Scroll here?
      </section>
      <section id="section3" style={{ height: "100vh" }}></section>
    </>
  );
};

...

<Router>
  <Routes>
    ...
    <Route path="/viewone" element={<ViewOne />} />
    <Route path="/viewtwo" element={<ViewTwo />} />
    ...
  </Routes>
</Router>

Edit react-change-view-and-then-scroll-to-element

Javanese answered 22/4, 2022 at 21:50 Comment(1)
Nice and concise answer! Love it and it works like a charm!Handicraft
P
1

you can use "useRef" to scroll to that position with click event or try useEffect for scroll to that position after component rendered.

const ViewTwo = () => {
    const scroller = useRef(null)
    const executeScroll = () => scroller.current.scrollIntoView()    

    return (
      <>
        <section style={{height: "100vh"}}></section>
        <section ref={scroller} style={{height: "100vh"}}>
          Scroll here?
        </section>
         <button onClick={executeScroll}> Click to scroll </button> 
        <section style={{height: "100vh"}}></section>
      </>);
    }
    export default ViewTwo;
Pointenoire answered 22/4, 2022 at 21:49 Comment(0)
K
0

If you're using react-router and looking for an easy way to navigate and scroll to an element (or just scroll without managing state in every component), I created this simple component called ScrollLink. It avoids the hassle of managing state and keeps things clean.

import React, { useEffect } from 'react';
import { Link, LinkProps, useLocation } from 'react-router-dom';

type ScrollLinkProps = LinkProps & {
  id: string;
  top?: number;
};

const ScrollLink: React.FC<ScrollLinkProps> = ({ to, id, top = 0, children, ...props }) => {
  const location = useLocation();

  const handleClick = () => {
    localStorage.setItem('scrollToId', id); 
  };

  useEffect(() => {
    const savedId = localStorage.getItem('scrollToId');
    if (savedId && location.pathname === to) {
      const element = document.getElementById(savedId);
      if (element) {
        const offset = element.getBoundingClientRect().top + window.scrollY - top;
        window.scrollTo({ top: offset, behavior: 'smooth' });
      }
      localStorage.removeItem('scrollToId'); 
    }
  }, [location]);

  return (
    <Link to={to} {...props} onClick={handleClick}>
      {children}
    </Link>
  );
};

export default ScrollLink;

How to Use

Assign an id to the target element you want to scroll to. For example:

<section id="contactsID">
  <!-- Your section content -->
  <h2>Contact Us</h2>
  <p>Feel free to reach out!</p>
</section>

Use the ScrollLink component wherever you want to link to that element, such as in a footer or navigation:

<ScrollLink to="/Contact" id="contactsID" top={70} className="flex items-center gap-2">
  <p>Contacts</p>
  <PiMapPinAreaLight size={20} />
</ScrollLink>

Explanation of Props

to: The path to navigate to (same as the to prop in react-router-dom's Link).

id: The ID of the element to scroll to once the page loads.

top (optional): Offset in pixels from the top of the page to the scrolled element. This is useful if you have fixed headers or navbars that would otherwise cover the element.

...props: You can also pass any other props supported by the Link component from react-router-dom, such as className, style, onClick, etc.

This approach allows you to navigate to a page and smoothly scroll to a specific element without needing to manage state across components. It’s a simple and reusable solution for scroll-based navigation in your React projects.

Kavanaugh answered 23/10 at 0:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.