What is the correct way of dealing with scroll position in React? I really like smooth scrolling because of better UX. Since manipulating the DOM in React is an anti-pattern I ran into problem: how to scroll smoothly to some position/element? I usually change scrollTop value of an element, but this is a manipulation on the DOM, which is not allowed.
JSBIN
code:
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
handleClick = e => {
for (let i = 1; i <= 100; i++) {
setTimeout(() => (this.node.scrollTop = i), i * 2);
}
};
render() {
const someArrayToMap = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
return (
<div ref={node => this.node = node} style={{overflow: 'auto', height: '100vh'}}>
<button onClick={this.handleClick}>CLICK TO SCROLL</button>
{
[...someArrayToMap,
...someArrayToMap,
...someArrayToMap,
...someArrayToMap,
...someArrayToMap,
...someArrayToMap,
...someArrayToMap].map((e, i) => <div key={i}>some text here</div>)
}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
How to achieve this in a React way?
You can just use refs and the scrollIntoView
method (with behavior: 'smooth'
for smooth scrolling). It's only a few lines of code and doesn't require a package.
Say this is what you want to scroll to
<p ref={this.myRef} className="scrollToHere">[1] ...</p>
And some sort of button
<button onClick={() => {this.scroll(this.myRef)}} className="footnote">[1]</button>
to call the scroll method
class App extends Component {
constructor() {
super()
this.myRef = React.createRef();
scroll(ref) {
ref.current.scrollIntoView({behavior: 'smooth'})
}
}
EDIT: Because this method is not yet supported by all browsers (overview of browser support), you might want to use a polyfill.
window.scroll({top: 0, left: 0, behavior: 'smooth' })
works for me.
You also need to check for browser's compability
Or use polyfill
A couple good packages out there already that can handle this for you:
https://github.com/fisshy/react-scroll - Demo
https://www.npmjs.com/package/react-scroll-to-component
Simple scroll to component
Hope this helps!
There are several libraries for scrolling to anchors in React. The one to choose depend on the features you're seeking and the existing setup of your page.
React Scrollable Anchor is a lightweight library that's specifically for scrolling to anchors that are mapped to URL hashes. It also updates the URL hash based on currently focused section. [Full disclosure: I'm the author of this library]
React Scroll, mentioned in another answer, is a more fully featured library for scrolling to anchors, without any reflection of location in the URL.
You can also hook up something like React Router Hash Link Scroll if you're already using React Router, which will then also tie into your URL hash.
I really enjoy the react-router website in the API section, they seem to use this scrollToDoc component that is a really sweet translation of a typical VanillaJS smooth-scroll function into React which depends on react-motion
!