1

I am doing this at some point in my React app:

document.getElementById(element).scrollIntoView({ behavior: "smooth" });

As a beginner, I have two questions around this:

1) Is this considered bad practice in React? Should I rather use refs?

2) Am I technically modifying the DOM in any way using this technique? As far as I know, I am not, but maybe there's something going on in the background I'm not aware of.

R. Kohlisch
  • 2,381
  • 6
  • 22
  • 49
  • 2
    The bad practice is that you’re tightly coupling your app to an environment where the document is available with these methods. You usually want to abstract environment assumptions like that away to future proof your code, which is what using refs does. It’s generally a good habit to have even if you’re fairly confident the document will always be there. No scrollIntoView doesn’t manipulate the Dom. – bryan60 Feb 28 '20 at 15:14
  • 2
    Because the DOM here doesn't get mutated, it's unlikely to cause much of a problem. But yes, using `refs` is the correct way. – Keith Feb 28 '20 at 15:15
  • Thanks a lot. So refs are preferable, mainly, because they do not assume the document to be present? – R. Kohlisch Feb 28 '20 at 15:18
  • 2
    Actually, the DOM is being manipulated, as much as `.style.color = "red"` manipulates the DOM. The `.scrollTop` values are being changed. – Heretic Monkey Feb 28 '20 at 15:19
  • @HereticMonkey `.scrolltop` but doing a diff of the DOM & the virtual DOM will be identical. `style.color` if using inline style would generate a DOM difference. I suppose the terminology should have been if the DOM to VDOM has not changed. – Keith Feb 28 '20 at 15:23
  • Does this answer your question? [ReactJS how to scroll to an element](https://stackoverflow.com/questions/43441856/reactjs-how-to-scroll-to-an-element) – Emile Bergeron Feb 28 '20 at 15:25
  • @EmileBergeron Thanks. No it doesn't. I know how to use `refs`, but i'm trying to avoid using refs because I have lots of components that would need a ref then. So I tried it with id + document.scrollIntoView, but I am not sure whether this is good practice in React or not. – R. Kohlisch Feb 28 '20 at 15:28
  • React doesn't have a built-in way to scroll to an element. Refs are React's way to "get an element" while avoiding all the mess you'll step into by trying to manage the DOM yourself. There's even an example of [how to use `scrollIntoView` with refs](https://stackoverflow.com/a/52528619/1218980). – Emile Bergeron Feb 28 '20 at 15:34
  • My Problem is not that I don't know how to use `scrollIntoView` with refs, my problem is that I am trying to avoid refs intentionally, because I'm trying to follow Steve McGuire's advice to never use refs. However, I don't know how to solve this without refs - well, I could use `ids` and `getElementById` - but how much better is this, if at all? It doesn't seem like a great alternative. Am I going wrong somewhere? – R. Kohlisch Feb 28 '20 at 15:39
  • You're misunderstanding the goal of avoiding refs. React is a one-way data flow. The goal when avoiding refs is to avoid going in the reverse order of the flow. So anything that reads the DOM is as bad as refs. The DOM is (re)generated from the data multiple times during the rendering life-cycle, reading the DOM is a huge performance issue in JavaScript that React is solving with its VDOM and the one-way data flow. – Emile Bergeron Feb 28 '20 at 15:46
  • The question I linked answers your question by proving that the best way to do scrolling _is_ to use refs, not by showing you _how_ to use refs. – Emile Bergeron Feb 28 '20 at 15:48
  • If you feel like your using refs a lot, well in coding terms that is. It might make sense to make it into a component,. maybe `` , this component could then be updated using state or props, depending on your use case. I think this is what is meant by avoiding refs, a bit like avoiding the Promise constructor pattern, you push it's use to lower level functions. – Keith Feb 28 '20 at 15:55
  • @EmileBergeron Sorry, I did not check out your link, because you labeled it as `how to use scrollIntoview with refs`, which is not what I'm looking for. If there is a good explanation in there *why* I should be using ref, I will check it out again. – R. Kohlisch Feb 28 '20 at 15:55
  • @Keith Can you explain this a bit further? So I would have this component, but wouldn't I still need refs to my elements that I need to scroll to? – R. Kohlisch Feb 28 '20 at 15:56
  • It's the auto-comment when voting to close as a duplicate. But now that I saw that you've posted 3 times about the same question, the best duplicate candidate is your [own initial question.](https://stackoverflow.com/q/60439016/1218980) – Emile Bergeron Feb 28 '20 at 15:58
  • 1
    You would still be internally using `refs`, but from your coding point of view, they will be controlled by the component. IOW: Your avoiding using `refs` because you have a centralised component that's handling the refs instead. So lets assume you later wanted to convert your app to maybe React Native, not sure but this maybe does scrollIntoView differently, then the good thing you have one component to update, rather than lots of pages were you have used refs. – Keith Feb 28 '20 at 16:04
  • @Keith Thanks a lot, that really helps me! So I am not avoiding refs because they are somehow slower than anything else. Got it. – R. Kohlisch Feb 28 '20 at 16:05

1 Answers1

6

In general, refs is better than document.getElementById, because it is more in line with the rest of your react code.

In react, every component class can have multiple component instances. Also using id is dangerous, because react does not prevent you to have multiple forms on 1 page, and then your DOM contains multiple inputs with same ID. And that is not allowed.

Another advantage to using refs, is that by design, you can only access the refs in the context where you define it. This forces you to use props and state (and possibly stores) if you need to access info outside of this context. And this an advantage, because there is less/ no chance of you breaking your unidirectional data flow, which would make your code less manageable.

NB: In almost all cases, refs can be avoided altogether. It is a design principle for Netflix to use no refs, ever, as explained by Steve McGuire (Senior User Interface Engineer at Netflix) in this video from reactjs conf 2016 (9:58m into the video). In your case, this would mean putting the email-input value in state of the form, add on onChange handler, and use the state value in the submit event.

Nitin Kumar
  • 119
  • 5
  • Thanks a lot. It's so funny you mention the Netflix talk about avoiding refs. This is why I am asking this and why I am trying to avoid refs, but in some cases I just don't know how. I don't know what exactly you mean by ` In your case, this would mean putting the email-input value in state of the form, add on onChange handler, and use the state value in the submit event.` ? I am trying to scroll to an element on submit, my problem is, I have lots of elements, so I am trying to avoid refs, but if I shouldn't use `document` and neither `ids` I don't know how to find the element and scroll to it – R. Kohlisch Feb 28 '20 at 15:25
  • 2
    -1. Although a correct answer, please refrain from copying other's **_without appropriate credits to the original author_**: [reactjs this.refs vs document.getElementById](https://stackoverflow.com/questions/37273876/reactjs-this-refs-vs-document-getelementbyid) – Danry Dec 30 '21 at 22:26