React: [useRef, scrollIntoView,] How to only autoscroll a specific div inside of an overflowing page?
Asked Answered
E

3

6

As you can see in my example

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

function App() {
  const items = ["this", "that", "those", "them", "these", "thisins"];

  const messagesRef = React.useRef(null);
  const scrollToBottom = () => {
    messagesRef.current.scrollIntoView({
      behavior: "smooth"
    });
  };

  React.useEffect(() => {
    if (messagesRef.current) {
      scrollToBottom();
    }
  }, [messagesRef]);

  return (
    // Page is overflowing, set height to mimic a full page
    <div className="App" style={{ marginTop: 70, height: 800 }}>
      {/* now set this div to overflow scroll with a small height */}
      <div style={{ overflowY: "scroll", height: 200, border: "solid" }}>
        {items.map(elem => (
          <div style={{ border: "solid", borderColor: "green", padding: 20 }}>
            {elem}
          </div>
        ))}
        {/* Set last element within this div to be the ref to scroll to */}
        <div ref={messagesRef} />
      </div>
    </div>
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

<div id="root"></div>

The page loads, and both the page and the nested scrolling div auto scroll.

What I'm trying to do is only scrollIntoView the overflowing div I have set as my ref.

I'm targetting the ref, and it is working, but how do I NOT scroll the parent element as well?

Esplanade answered 18/2, 2020 at 21:21 Comment(3)
Interestingly enough your code causes the parent frame to scroll as well...Tang
right, that is the essence of what I'm trying to subvertEsplanade
scrollToBottom should also be added as a dependency of the useEffect hook.Papeterie
R
15

Try this:

   messagesRef.current.scrollIntoView({
      behavior: "smooth",
      block: "nearest",
      inline: "start"
    });
Ryannryazan answered 18/2, 2020 at 21:30 Comment(1)
How to give margin-top(offset) ?Necrophilia
I
0

I was having an issue with it scrolling to the top with the above configuration. I just added the behavior: "smooth" option and it works perfectly :)

Create the ref to the element:

const recogRef = useRef();

I have this in a switch statement inside the userActions method that checks the onClick event:

case "recognition":
  recogRef.current.scrollIntoView({
    behavior: "smooth",
  });
  break

Then add the ref to an element you want to scroll to:

<h3 ref={recogRef} className="m-0">
  Recognitions for {`${participant.firstName}`}
</h3>

Note, this was in an Object.keys(obj).map methon
And then the element that triggers the action call:

<div
  key={key}
  onClick={() => userActions(key)}
  className="user_action d-flex align-items-center justify-content-center"
>
  <p className="mb-0 ms-1 fw-bold">{actions[key].label<}/p>
</div>

Isidore answered 14/4, 2022 at 15:51 Comment(0)
A
0

i tried this use case in react and work for horizontal scroll

    useEffect(() => {
     const element = document.getElementById(selectedDay);
     if (element) {
      element.scrollIntoView({
      behavior: "smooth",
      block: "end",
      inline: "nearest"
     });
     }
     }, [selectedDay]);
Abominable answered 4/5, 2023 at 10:17 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Shanell

© 2022 - 2024 — McMap. All rights reserved.