439

I have a chat widget that pulls up an array of messages every time I scroll up. The problem I am facing now is the slider stays fixed at the top when messages load. I want it to focus on the last index element from the previous array. I figured out that I can make dynamic refs by passing index, but I would also need to know what kind of scroll function to use to achieve that

 handleScrollToElement(event) {
    const tesNode = ReactDOM.findDOMNode(this.refs.test)
    if (some_logic){
      //scroll to testNode      
    }
  }

  render() {

    return (
      <div>
        <div ref="test"></div>
      </div>)
  }
edmamerto
  • 7,605
  • 11
  • 42
  • 66

30 Answers30

775

React 16.8 +, Functional component

const ScrollDemo = () => {
   const myRef = useRef(null)

   const executeScroll = () => myRef.current.scrollIntoView()    
   // run this function from an event handler or an effect to execute scroll 

   return (
      <> 
         <div ref={myRef}>Element to scroll to</div> 
         <button onClick={executeScroll}> Click to scroll </button> 
      </>
   )
}

Click here for a full demo on StackBlitz

React 16.3 +, Class component

class ReadyToScroll extends Component {
    constructor(props) {
        super(props)
        this.myRef = React.createRef()  
    }

    render() {
        return <div ref={this.myRef}>Element to scroll to</div> 
    }  

    executeScroll = () => this.myRef.current.scrollIntoView()
    // run this method to execute scrolling. 
}

Class component - Ref callback

class ReadyToScroll extends Component {  
    render() {
        return <div ref={ (ref) => this.myRef=ref }>Element to scroll to</div>
    } 

    executeScroll = () => this.myRef.scrollIntoView()
    // run this method to execute scrolling. 
}

Don't use String refs.

String refs harm performance, aren't composable, and are on their way out (Aug 2018).

string refs have some issues, are considered legacy, and are likely to be removed in one of the future releases. [Official React documentation]

resource1resource2

Optional: Smoothe scroll animation

/* css */
html {
    scroll-behavior: smooth;
}

Passing ref to a child

We want the ref to be attached to a dom element, not to a react component. So when passing it to a child component we can't name the prop ref.

const MyComponent = () => {
    const myRef = useRef(null)
    return <ChildComp refProp={myRef}></ChildComp>
} 

Then attach the ref prop to a dom element.

const ChildComp = (props) => {
    return <div ref={props.refProp} />
}
Gama11
  • 31,714
  • 9
  • 78
  • 100
Ben Carp
  • 24,214
  • 9
  • 60
  • 72
  • 11
    `window.scrollTo(0, offsetTop)` is a better option with better support among current browsers – MoMo Oct 02 '18 at 11:10
  • 1
    Could make sure you are consistent in your exemple. We're starting from myRef, going with domRef, and ending with tesNode ?. That is quite confusing – Louis Lecocq Oct 02 '18 at 12:42
  • My anchor links and the sections I would like to scroll to are not in the same component. How to access the ref of the section in my Link? – Simon Franzen Oct 18 '18 at 17:05
  • 10
    Obvious after the fact, but it is important to mention that this only works for native DOM elements and not just any React component. – telliks Nov 01 '18 at 19:19
  • 1
    @jpunk11 I just updated my answer. The updated answer explains how to scroll to a dom element which is in a child class component. – Ben Carp Nov 08 '18 at 17:07
  • 2
    @SimonFranzen Take a look at my updated answer - TLDR - class component case. When scrollToMyRef is called it will scroll to the child you attached the ref to. You can pass the method to a different child component, and trigger it from there. – Ben Carp Nov 08 '18 at 17:28
  • 1
    this.myRef.current.getBoundingClientRect().top work for my case, this.myRef.current.top does not return correct element position. – HungDQ Dec 26 '18 at 03:25
  • @HungDQ, are you sure the comment refers to my answer? This is about scrolling not getting the position of an element. – Ben Carp Dec 26 '18 at 08:18
  • Thanks for the detailed answer. Regarding the use of `useScroll`, I wonder how this could be attached to a button click event? I mean beside scrolling I want to perform some other tasks as well. But, this does no seem to be possible with ` – renakre Jul 13 '19 at 16:17
  • @renakre, Is this what you are looking for? https://stackblitz.com/edit/react-eeqkhn . Look at lines 30-33 – Ben Carp Jul 13 '19 at 18:28
  • none of them not gonna work if you want to scroll inside an element like Material ui Dialog etc – Shin Jul 20 '19 at 20:37
  • @Shin, I think it's out of scope for this question. If you can't find it in an existing Stackoverflow perhaps you can ask a new question. – Ben Carp Jul 21 '19 at 03:29
  • Check out my newer answer https://stackoverflow.com/questions/43441856/reactjs-how-to-scroll-to-an-element/57135211#57135211 – Ben Carp Aug 09 '19 at 08:24
  • 1
    Awesome answer, but this is not compatible with safari? – Otto Oct 07 '19 at 09:24
  • @Otto, I'd like to check into it when I have time. Can you provide some more details? My experience in general is that it does work in Safari, so can you please let me know which option you used, and if it failed on mobile or desktop Safari? Also what version of Safari? – Ben Carp Oct 07 '19 at 11:07
  • @BenCarp Well the offset works. But in safari the `scroll-behaviour: smooth` is not supported. – Otto Oct 08 '19 at 15:58
  • @BenCarp I used the class component, and also passing to child components. It fails on desktop safari 13.0.1. – Otto Oct 08 '19 at 16:06
  • @Otto, so it does scroll, only the animation fails - right? – Ben Carp Oct 08 '19 at 16:09
  • @BenCarp yes exactly – Otto Oct 08 '19 at 16:12
  • @otto, there are two ways to achieve smooth scroll animation I know. First is via css as described above. Second is passing a second options parameter to window.scroll (or element.scrollTo). Unfortunately Safari doesn't support either. https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior . See Browser compatability at the bottom. – Ben Carp Oct 08 '19 at 16:16
  • @Otto there are some JS solutions that can make it work, but it is out of scope for this answer. – Ben Carp Oct 08 '19 at 16:20
  • I would suggest a safer version of scroll function with backward compatibility: ` function scrollTopWindowTop(top = 0) { try { window && window.scroll({ top, left: 0, behavior: 'smooth' }); } catch (error) { window && window.scrollTo(0, 0); } };` – Oleg G Feb 23 '20 at 14:53
  • In dynamic context it is advised to use `setTimeout` to let the DOM build your elements – Oleg G Feb 23 '20 at 14:58
  • @OlegG, what do you mean? – Ben Carp Feb 23 '20 at 15:44
  • @BenCarp In the example implied by the OP, scrolling is performed after the action (say, click) of the user (i.e when the DOM is well and built). But if you would like to scroll when the user is re-routed to a different page and taken to a specific element, then you have to take into account that at the time of the scrollTo the element may yet not exist. Thus, `const scrollTimer = useRef(0); ` followed by `scrollTimer.current = setTimeout(() => scrollTopWindowTop(myRef.current.offsetTop), 0);` Somewhere on unmount you should also `scrollTimer && clearTimeout(scrollTimer.current);` – Oleg G Feb 23 '20 at 19:31
  • So if my button which initiates scrolling is a distant cousin of the component to be scrolled to, I have to pass a ref all the way up from the button, to the common ancestor, then all the way back down the other way to the component being scrolled to? That sounds insane. – sammy Jul 29 '20 at 09:00
  • @sammy, not exactly. You'll create the ref and the handler in the common parent. Then pass the handler down to the button, and the ref down to the element you want to scroll to. That is the React way to do it. But React does give you excellent tools to pass props to deeply nested components - context. Context could definitely help you here. To be honest, there is an alternative which is simpler. But that should be the exception, and I'd rather avoid it if possible. Give the element you want to scroll to an id, and then use that id to get the element and execute the scroll. – Ben Carp Jul 29 '20 at 10:39
  • I didn't know I could getElementById in React. Passing the ref through 10 different components would be a circus in my case, hard to debug later. I'll use React for what it's good at, but I won't force a circle peg into a square hole. I'll use the id like you say in this case. Thanks for the tip. – sammy Jul 30 '20 at 01:59
  • For multiple navigation in the same page use `scrollToRef = (ref) => window.scrollTo(0, ref.current.offsetTop) ` – YaakovHatam Sep 08 '20 at 08:14
  • If your DOM element is `position: relative`, then you need to alter it: `window.scrollTo(0, ref.current.offsetParent.offsetTop)` – Koli Nov 04 '20 at 09:34
  • Previously in my same project myRef.current.scrollTo(0, 0) was working, but suddenly it stopped working for new code. But finally, I have changed this to myRef.current.scrollIntoView() and it's working. Thanks – santosh devnath Feb 22 '21 at 12:52
  • @santoshdevnath, did you change a parent element to be positioned (position: relative|absolute|sticky)? – Ben Carp Feb 22 '21 at 15:52
  • @BenCarp my parent div is a sticky header – santosh devnath Feb 23 '21 at 05:33
  • `ref={ (ref) => this.myRef=ref }` this didn't work for me (using class component) I had to do `ref={ (ref) => this.myRef.current=ref }`. – Displee Dec 30 '21 at 12:42
  • @Displee, can you provide a sandbox? `this.ref.current` should only be relevant if you use `createRef()` – Ben Carp Jan 15 '22 at 19:42
  • In typescript, `Object is possibly 'null'.ts(2531)` – CCCC Dec 28 '22 at 07:27
143

this worked for me

this.anyRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' })

EDIT: I wanted to expand on this based on the comments.

const scrollTo = (ref) => {
  if (ref && ref.current /* + other conditions */) {
    ref.current.scrollIntoView({ behavior: 'smooth', block: 'start' })
  }
}

<div ref={scrollTo}>Item</div>
lwdthe1
  • 1,001
  • 1
  • 16
  • 16
chii
  • 2,111
  • 3
  • 17
  • 21
65

I had a simple scenario, When user clicks on the menu item in my Material UI Navbar I want to scroll them down to the section on the page. I could use refs and thread them through all the components but I hate threading props through multiple components because that makes code fragile.

I just used vanilla JS in my react component, turns out it works just fine. Placed an ID on the element I wanted to scroll to and in my header component I just did this.

const scroll = () => {
  const section = document.querySelector( '#contact-us' );
  section.scrollIntoView( { behavior: 'smooth', block: 'start' } );
};
Jose
  • 1,959
  • 20
  • 21
  • I needed to scroll from a click in component A to an element in component B. This worked perfectly! – av av Aug 04 '20 at 22:02
  • 1
    Perfect! works in 2023 with React – Chefk5 May 19 '23 at 09:01
  • is it bad practice to use `document.querySelector()` instead of `ref`? is it an anti-pattern? – yeln Aug 23 '23 at 08:46
  • Yes this is technically an anti-pattern, the preferred approach is using refs. However if your component is not close to your other one in your component tree then threading refs is a nightmare. I made a trade off decision that in this case it was fine to not use refs due to technical complexity that came with using a ref. – Jose Aug 24 '23 at 22:13
48

Just find the top position of the element you've already determined https://www.w3schools.com/Jsref/prop_element_offsettop.asp then scroll to this position via scrollTo method https://www.w3schools.com/Jsref/met_win_scrollto.asp

Something like this should work:

handleScrollToElement(event) {
  const tesNode = ReactDOM.findDOMNode(this.refs.test)
  if (some_logic){
    window.scrollTo(0, tesNode.offsetTop);
  }
}

render() {

  return (
    <div>
      <div ref="test"></div>
    </div>)
}

UPDATE:

since React v16.3 the React.createRef() is preferred

constructor(props) {
  super(props);
  this.myRef = React.createRef();
}

handleScrollToElement(event) {
  if (<some_logic>){
    window.scrollTo(0, this.myRef.current.offsetTop);
  }
}

render() {

  return (
    <div>
      <div ref={this.myRef}></div>
    </div>)
}
Roman Maksimov
  • 1,537
  • 1
  • 9
  • 14
  • 3
    This is the better answer. Using `ReactDOM.findDomNode()` is better practice - since React re-renders components, a div that you simply get by its ID might not exist by the time you call the function – Good Idea Jul 03 '17 at 04:04
  • 5
    According to the official documentation you should try to avoid using `findDOMNode`. In most cases, you can attach a ref to the DOM node and avoid using `findDOMNode` at all. – Facyo Kouch Jan 22 '18 at 20:11
  • 1
    Note that using this.refs by string mapping is deprecated, see: https://stackoverflow.com/questions/43873511/deprecation-warning-using-this-refs – Himmet Avsar Jul 10 '18 at 13:25
  • 1
    Note: I had to use `this.myRef.current.scrollIntoView()` instead of `window.scrollTo(0, this.myRef)`. – Babbz77 Oct 24 '18 at 19:17
20

Jul 2019 - Dedicated hook/function

A dedicated hook/function can hide implementation details, and provides a simple API to your components.

React 16.8 + Functional Component

const useScroll = () => {
  const elRef = useRef(null);
  const executeScroll = () => elRef.current.scrollIntoView();

  return [executeScroll, elRef];
};

Use it in any functional component.

const ScrollDemo = () => {
    const [executeScroll, elRef] = useScroll()
    useEffect(executeScroll, []) // Runs after component mounts
    
    return <div ref={elRef}>Element to scroll to</div> 
}

full demo

React 16.3 + class Component

const utilizeScroll = () => {
  const elRef = React.createRef();
  const executeScroll = () => elRef.current.scrollIntoView();

  return { executeScroll, elRef };
};

Use it in any class component.

class ScrollDemo extends Component {
  constructor(props) {
    super(props);
    this.elScroll = utilizeScroll();
  }

  componentDidMount() {
    this.elScroll.executeScroll();
  }

  render(){
    return <div ref={this.elScroll.elRef}>Element to scroll to</div> 
  }
} 

Full demo

Ben Carp
  • 24,214
  • 9
  • 60
  • 72
  • For anyone using Typescript, you should declare the return type of `useScroll` as `[() => void, RefObject] `. Then you can call `executeScroll()` without issues – kasztof Jan 10 '22 at 14:48
  • 1
    @kasztof, I a TS fan, but I heard a strong opinion that TS should not be used in JS SOF questions, as it can make it more difficult to understand to non TS developers. I know the issue you are facing. You can also cast the return as const. We can add TS defintions in a comment, or at the end of the answer. – Ben Carp Jan 10 '22 at 18:48
  • 1
    TypeScript: const myRef = useRef(null); const executeScroll = () => { if (myRef.current) { myRef.current.scrollIntoView(); } }; – user42488 May 04 '23 at 07:09
18

You can now use useRef from react hook API

https://reactjs.org/docs/hooks-reference.html#useref

declaration

let myRef = useRef()

component

<div ref={myRef}>My Component</div>

Use

window.scrollTo({ behavior: 'smooth', top: myRef.current.offsetTop })
  • I'm trying to use your code. I can see, through `console.log` that it's executing your `window.scrollTo` statement (adjusted for my case) but yet it doesn't scroll. Might this be related to the fact that I'm using a React Bootstrap Modal? – robertwerner_sf Oct 17 '19 at 23:57
14

Using findDOMNode is going to be deprecated eventually.

The preferred method is to use callback refs.

github eslint

Afaq Ahmed Khan
  • 2,164
  • 2
  • 29
  • 39
sww314
  • 1,252
  • 13
  • 17
  • 3
    Please include the relevant part of the linked material so in case that gets removed your answer doesn't become useless. – totymedli Dec 10 '18 at 07:51
11

The nicest way is to use element.scrollIntoView({ behavior: 'smooth' }). This scrolls the element into view with a nice animation.

When you combine it with React's useRef(), it can be done the following way.

import React, { useRef } from 'react'

const Article = () => {
  const titleRef = useRef()

  function handleBackClick() {
      titleRef.current.scrollIntoView({ behavior: 'smooth' })
  }

  return (
      <article>
            <h1 ref={titleRef}>
                A React article for Latin readers
            </h1>

            // Rest of the article's content...

            <button onClick={handleBackClick}>
                Back to the top
            </button>
        </article>
    )
}

When you would like to scroll to a React component, you need to forward the ref to the rendered element. This article will dive deeper into the problem.

robinvdvleuten
  • 1,462
  • 1
  • 16
  • 18
  • 1
    This is way better. I was originally doing `(ref) => window.scrollTo(0, ref.current.offsetTop) ` but then only getting a small offset from the top and not arriving at target. I believe this was because the ref's location was someone calculated in the beginning and then not updated. Your suggestion fixed my problem while the accepted answer didn't. – Willy Jul 20 '20 at 20:53
10

You can also use scrollIntoView method to scroll to a given element.

handleScrollToElement(event) {
const tesNode = ReactDOM.findDOMNode(this.refs.test)
 if (some_logic){
  tesNode.scrollIntoView();
  }
 }

 render() {
  return (
   <div>
     <div ref="test"></div>
   </div>)
}
Farshad J
  • 111
  • 1
  • 6
10

I might be late to the party but I was trying to implement dynamic refs to my project the proper way and all the answer I have found until know aren't quiet satisfying to my liking, so I came up with a solution that I think is simple and uses the native and recommended way of react to create the ref.

sometimes you find that the way documentation is wrote assumes that you have a known amount of views and in most cases this number is unknown so you need a way to solve the problem in this case, create dynamic refs to the unknown number of views you need to show in the class

so the most simple solution i could think of and worked flawlessly was to do as follows

class YourClass extends component {

state={
 foo:"bar",
 dynamicViews:[],
 myData:[] //get some data from the web
}

inputRef = React.createRef()

componentDidMount(){
  this.createViews()
}


createViews = ()=>{
const trs=[]
for (let i = 1; i < this.state.myData.lenght; i++) {

let ref =`myrefRow ${i}`

this[ref]= React.createRef()

  const row = (
  <tr ref={this[ref]}>
<td>
  `myRow ${i}`
</td>
</tr>
)
trs.push(row)

}
this.setState({dynamicViews:trs})
}

clickHandler = ()=>{

//const scrollToView = this.inputRef.current.value
//That to select the value of the inputbox bt for demostrate the //example

value=`myrefRow ${30}`

  this[value].current.scrollIntoView({ behavior: "smooth", block: "start" });
}


render(){

return(
<div style={{display:"flex", flexDirection:"column"}}>
<Button onClick={this.clickHandler}> Search</Button>
<input ref={this.inputRef}/>
<table>
<tbody>
{this.state.dynamicViews}
<tbody>
<table>
</div>


)

}

}

export default YourClass

that way the scroll will go to whatever row you are looking for..

cheers and hope it helps others

Afaq Ahmed Khan
  • 2,164
  • 2
  • 29
  • 39
Miguel Sedek
  • 173
  • 2
  • 11
9

This solution works for me in ReactJS

In header.js

function scrollToTestDiv(){
      const divElement = document.getElementById('test');
      divElement.scrollIntoView({ behavior: 'smooth' });
    }

<a class="nav-link" onClick={scrollToTestDiv}> Click here! </a>

In index.html

<div id="test"></div>
user3349907
  • 317
  • 3
  • 3
7

You could try this way:

 handleScrollToElement = e => {
    const elementTop = this.gate.offsetTop;
    window.scrollTo(0, elementTop);
 };

 render(){
  return(
      <h2 ref={elem => (this.gate = elem)}>Payment gate</h2>
 )}
p-a-o-l-o
  • 9,807
  • 2
  • 22
  • 35
7
<div id="componentToScrollTo"><div>

<a href='#componentToScrollTo'>click me to scroll to this</a>
Robert O'Toole
  • 197
  • 1
  • 11
5

You can use something like componentDidUpdate

componentDidUpdate() {
  var elem = testNode //your ref to the element say testNode in your case; 
  elem.scrollTop = elem.scrollHeight;
};
Raviteja
  • 3,399
  • 23
  • 42
  • 69
  • 3
    i think using element id is not preferred in react. It breaks the virtual dom concept – iamsaksham Mar 12 '18 at 03:31
  • Using the life cycle method is the way to go as far as WHEN/WHERE to run the code. But probably want to use the other methodologies you see in this answer for the actual code – Dameo Jul 20 '18 at 16:15
5

Here is the Class Component code snippet you can use to solve this problem:

This approach used the ref and also scrolls smoothly to the target ref

import React, { Component } from 'react'

export default class Untitled extends Component {
  constructor(props) {
    super(props)
    this.howItWorks = React.createRef() 
  }

  scrollTohowItWorks = () =>  window.scroll({
    top: this.howItWorks.current.offsetTop,
    left: 0,
    behavior: 'smooth'
  });

  render() {
    return (
      <div>
       <button onClick={() => this.scrollTohowItWorks()}>How it works</button>
       <hr/>
       <div className="content" ref={this.howItWorks}>
         Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nesciunt placeat magnam accusantium aliquid tenetur aspernatur nobis molestias quam. Magnam libero expedita aspernatur commodi quam provident obcaecati ratione asperiores, exercitationem voluptatum!
       </div>
      </div>
    )
  }
}
bello hargbola
  • 435
  • 6
  • 9
5

If anyone is using Typescript, here is Ben Carp's answer for it:

import { RefObject, useRef } from 'react';

export const useScroll = <T extends HTMLElement>(
  options?: boolean | ScrollIntoViewOptions
): [() => void, RefObject<T>] => {
  const elRef = useRef<T>(null);
  const executeScroll = (): void => {
    if (elRef.current) {
      elRef.current.scrollIntoView(options);
    }
  };

  return [executeScroll, elRef];
};
Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
Fabian Sievert
  • 810
  • 5
  • 15
  • 1
    Your answer could probably benefit from a link, a definition for `ScrollIntoViewOptions`, and an example usage. – jmealy Mar 03 '22 at 02:31
5

You can use useRef along with scrollIntoView.

  • use useReffor the element you want to scroll to: here I want to sroll to the PieceTabs element that is why I wrap it with a Box(div) so I can get access to the dom elemnt

You might be familiar with refs primarily as a way to access the DOM. If you pass a ref object to React with , React will set its .current property to the corresponding DOM node whenever that node changes. See the doc

...
const tabsRef = useRef()
...
<Box ref={tabsRef}>
   <PieceTabs piece={piece} value={value} handleChange={handleChange} />
</Box>
...
  • Create a function that handle this sroll:
  const handleSeeCompleteList = () => {
    const tabs = tabsRef.current
    if (tabs) {
      tabs.scrollIntoView({
        behavior: 'smooth',
        block: 'start',
      })
    }
  }
  • Call this function on the element you want once you click to scroll to the target:
 <Typography
  variant="body2"
  sx={{
    color: "#007BFF",
    cursor: "pointer",
    fontWeight: 500,
  }}
  onClick={(e) => {
    handleChange(e, 2);
    handleSeeCompleteList(); // here we go
  }}
>
  Voir toute la liste
</Typography>;

And here we go React Js Scroll to using useRef and scrollIntoView

DINA TAKLIT
  • 7,074
  • 10
  • 69
  • 74
4

Follow these steps:

1) Install:

npm install react-scroll-to --save

2) Import the package:

import { ScrollTo } from "react-scroll-to";

3) Usage:

class doc extends Component {
  render() {
    return(
      <ScrollTo>
        {({ scroll }) => (
          <a onClick={() => scroll({ x: 20, y: 500, , smooth: true })}>Scroll to Bottom</a>
        )}
      </ScrollTo>
    )
  }
}
Azametzin
  • 5,223
  • 12
  • 28
  • 46
Zahid Ali
  • 81
  • 1
  • 2
  • This library `react-scroll-to` is quite useful when multiple components are present or ref passing is complex. – abhishake Jun 29 '22 at 20:05
4

I used this inside a onclick function to scroll smoothly to a div where its id is "step2Div".

let offset = 100;
window.scrollTo({
    behavior: "smooth",
    top:
    document.getElementById("step2Div").getBoundingClientRect().top -
    document.body.getBoundingClientRect().top -
    offset
});
  • Here I guess your page has fixed number of elements because you have hardcoded the value of 'offset'. How will you solve the scrolling if the elements in your page are dynamically rendered basis the dynamic response from say an API. – utkarsh-k Nov 19 '20 at 10:47
4

After reading through manny forums found a really easy solution.

I use redux-form. Urgo mapped redux-from fieldToClass. Upon error I navigate to the first error on the list of syncErrors.

No refs and no third party modules. Just simple querySelector & scrollIntoView

handleToScroll = (field) => {

    const fieldToClass = {
        'vehicleIdentifier': 'VehicleIdentifier',
        'locationTags': 'LocationTags',
        'photos': 'dropzoneContainer',
        'description': 'DescriptionInput',
        'clientId': 'clientId',
        'driverLanguage': 'driverLanguage',
        'deliveryName': 'deliveryName',
        'deliveryPhone': 'deliveryPhone',
        "deliveryEmail": 'deliveryEmail',
        "pickupAndReturn": "PickupAndReturn",
        "payInCash": "payInCash",
    }

document?.querySelector(`.${fieldToClasses[field]}`)
         .scrollIntoView({ behavior: "smooth" })

}
Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
4

In order to automatically scroll into the particular element, first need to select the element using document.getElementById and then we need to scroll using scrollIntoView(). Please refer the below code.

   scrollToElement= async ()=>{
      document.getElementById('id001').scrollIntoView();
    } 

The above approach worked for me.

Senthuran
  • 1,583
  • 2
  • 15
  • 19
4

How to scroll to certain element in Reactjs during page render

import React, { useEffect, useRef } from 'react'

const YourComponent = () => {
  const yourElementRef = useRef(null);

  useEffect(() => {
    if (yourElementRef.current) {
      yourElementRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, []);

  return (
    <div ref={yourElementRef}>Element to scroll to</div>
  );
}

How to scroll to certain element in Reactjs when a state changes

import React, { useEffect, useRef, useState } from 'react'

const YourComponent = () => {
  const [stateValue, setStateValue] = useState()
  const yourElementRef = useRef(null);

  useEffect(() => {
    if (yourElementRef.current) {
      yourElementRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, [stateValue]);

  return (
    <div ref={yourElementRef}>Element to scroll to</div>
  );
}
Oluwagbemi Kadri
  • 400
  • 5
  • 15
3

If you want to do it on page load you can use useLayoutEffect, and useRef.

import React, { useRef, useLayoutEffect } from 'react'

const ScrollDemo = () => {

   const myRef = useRef(null)

   useLayoutEffect(() => {
      window.scrollTo({
        behavior: "smooth",
        top: myRef.current.offsetTop,
      });
    }, [myRef.current]);

   return (
      <> 
         <div ref={myRef}>I wanna be seen</div>
      </>
   )
}
Bruno Pintos
  • 363
  • 3
  • 10
2

What worked for me:

class MyComponent extends Component {
    constructor(props) {
        super(props);
        this.myRef = React.createRef(); // Create a ref    
    }

    // Scroll to ref function
    scrollToMyRef = () => {
        window.scrollTo({
            top:this.myRef.offsetTop, 
            // behavior: "smooth" // optional
        });
    };

    // On component mount, scroll to ref
    componentDidMount() {
        this.scrollToMyRef();
    }

    // Render method. Note, that `div` element got `ref`.
    render() {
        return (
            <div ref={this.myRef}>My component</div>
        )
    }
}
Artur Barseghyan
  • 12,746
  • 4
  • 52
  • 44
2

To anyone else reading this who didn't have much luck with the above solutions or just wants a simple drop-in solution, this package worked for me: https://www.npmjs.com/package/react-anchor-link-smooth-scroll. Happy Hacking!

User59
  • 487
  • 4
  • 19
1

Just a heads up, I couldn't get these solutions to work on Material UI components. Looks like they don't have the current property.

I just added an empty div amongst my components and set the ref prop on that.

Steve
  • 4,372
  • 26
  • 37
1

Here is my solution:

I put an invisible div inside main div and made its position absolute. Then set the top value to -(header height) and set the ref on this div. Or you can just react that div with children method.

It's working great so far!

<div className="position-relative">
        <div style={{position:"absolute", top:"-80px", opacity:0, pointerEvents:'none'}}  ref={ref}></div>
Halil Şağan
  • 139
  • 1
  • 3
1

Maybe someone meets situation like me

https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node

How can I measure a DOM node? One rudimentary way to measure the position or size of a DOM node is to use a callback ref. React will call that callback whenever the ref gets attached to a different node. Here is a small demo:

function MeasureExample() {
  const [height, setHeight] = useState(0);

  const measuredRef = useCallback(node => {
    if (node !== null) {
      setHeight(node.getBoundingClientRect().height);// you can scroll in this line 
    }
  }, []);

  return (
    <>
      <h1 ref={measuredRef}>Hello, world</h1>
      <h2>The above header is {Math.round(height)}px tall</h2>
    </>
  );
}

We didn’t choose useRef in this example because an object ref doesn’t notify us about changes to the current ref value. Using a callback ref ensures that even if a child component displays the measured node later (e.g. in response to a click), we still get notified about it in the parent component and can update the measurements.

Note that we pass [] as a dependency array to useCallback. This ensures that our ref callback doesn’t change between the re-renders, and so React won’t call it unnecessarily.

In this example, the callback ref will be called only when the component mounts and unmounts, since the rendered component stays present throughout any rerenders. If you want to be notified any time a component resizes, you may want to use ResizeObserver or a third-party Hook built on it.

colining
  • 11
  • 1
0
 <div onScrollCapture={() => this._onScrollEvent()}></div>

 _onScrollEvent = (e)=>{
     const top = e.nativeEvent.target.scrollTop;
     console.log(top); 
}
ibamboo
  • 1,467
  • 13
  • 15
0

This is the easiest way I find working for me. Just use normal javascript syntax no need for much packages

  const scrollTohowItWorks = () =>  window.scroll({
    top: 2000,
    left: 0,
    behavior: 'smooth'
  });
  
  <NavLink onClick={scrollTohowItWorks} style={({ isActive }) => isActive? {color: '#e26702', fontWeight:'bold'}: { color: '#0651b3'}} to=''>Support</NavLink>