Jay Shi
Jay Shi

Reputation: 195

scroll into view after routing in react

How to scroll into view after routing in react

We are using react-router. What I want to achieve is do a scroll into view on one of component after react route to that page.

Upvotes: 3

Views: 2814

Answers (3)

Afelaia Timur
Afelaia Timur

Reputation: 59

All of these solution seem to be wrong

  • what expected is on click -> route -> scroll into a view With above examples what will happen is on any render you scroll a particular element into a view... The behaviour for general componentDidMount should stay as is ...

You can either add a hash to a routing to distinguish if it's a render from let's say page a - > then on page itself check if there is param in query. Then the behaviour will be clean for componentDidMount.

For the above answers which i don't find correct you can use

useSmoothScroll(
    target: string,
    options: {
        freezeStickyComponents?: boolean
        hashLocation?: string
        offset?: number | boolean
        preventDefault?: boolean
    } = {},
    callback: (hash?: string) => void = DEFAULT_CALLBACK
): UseSmoothScrollCallback {
    const defaultOptions = {
        freezeStickyComponents: true,
        hashLocation: null,
        offset: false,
        preventDefault: true
    }
    options = { ...defaultOptions, ...options }
    const hasHash = options.hashLocation || target
    const hash = hasHash && `${hasHash}`
    const { freeze } = useStickyState()

    return useCallback(
        (event: SyntheticEvent<HTMLElement>): void => {
            if (options.preventDefault) {
                event.preventDefault()
            }

            if (!target) {
                scrollToTop(callback)
                return
            }
            const reference = document.getElementById(target)

            if (typeof options.offset === 'number') {
                window.scroll({
                    top:
                        reference?.getBoundingClientRect().top +
                        window.scrollY -
                        options.offset,
                    behavior: 'smooth'
                })
            } else {
                reference?.scrollIntoView({
                    behavior: 'smooth'
                })
            }

            window.history.pushState(null, null, hash)
            callback(hash)

            if (options.freezeStickyComponents) {
                freeze(800)
            }
        },
        // eslint-disable-next-line react-hooks/exhaustive-deps
        [freeze, hash, options, target]
    )
}

Upvotes: 0

Cat_Enthusiast
Cat_Enthusiast

Reputation: 15688

Here's a quick example for you using react-router-dom and refs. You didn't provide any code for us to look at so consider this a template. :)

Also here's a sandbox for your reference: https://codesandbox.io/s/adoring-surf-h55ci

So let's say your Routes are set-up like this:

Routes

function App() {
  return (
    <BrowserRouter>
      <div>
        <Route path="/" exact component={Home} />
        <Route path="/example" component={Example} />
      </div>
    </BrowserRouter>
  );
}

So user starts out at Home "/"

import React from "react";
import { Link } from "react-router-dom";

const Home = () => {
  return <Link to="/example">Go To Example</Link>;
};

export default Home;

They click on the link and it takes them to the /example route, rendering Example

import React from "react";
import Section from "./Section";

class Example extends React.Component {
  componentDidMount() {
    if (this.mySection.current) {
      this.mySection.current.scrollIntoView({
        behavior: "smooth",
        nearest: "block"
      });
    }
  }

  mySection = React.createRef();

  render() {
    return (
      <div>
        <div style={{ background: "orange", height: "750px" }}>
          This is an example, below is my component.
        </div>
        <div ref={this.mySection}>
          <Section />
        </div>
      </div>
    );
  }
}

export default Example;

Example has two parts, a div with plain text and the Section component. As you noticed, we wrap the Section component in a div and gave it a ref prop. The ref lets us communicate with that wrapper-div. In componentDidMount(), we just scroll to that div.

Upvotes: 4

alexr89
alexr89

Reputation: 410

One way to scroll to a component would be to put a ref on the component you want to scroll to: https://reactjs.org/docs/refs-and-the-dom.html

Once you have put the ref onto the component, you could then scroll to your ref in the componentDidMount() of the parent component, something like:

window.scrollTo(0, this.myRef.current.offsetTop)

You may need to be slightly more defensive here, and do something like this:

this.myRef && window.scrollTo(0, this.myRef.current.this.myRef)

This way, when the route is visited, the component will be scrolled to its offsetTop

Upvotes: 1

Related Questions