Reputation: 195
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
Reputation: 59
All of these solution seem to be wrong
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
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:
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
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