'Cannot position react-perfect-scrollbar with scrollTop using React hooks

I have an array of objects being rendered in a table with a react-perfect-scrollbar instance.

The code is the following:

const myComponent = ({ myArray }) => {      
  const scrollBarRef = useRef(null);
  useEffect(() => {
    const timer = setTimeout(() => {
      scrollBarRef.current.updateScroll()    
    }, 500);
    return () => clearTimeout(timer);
  }, []);

  useEffect(() => {
    const timer2 = setTimeout(() => {
      scrollBarRef.current.scrollTop = 200;
    }, 2500);
    return () => clearTimeout(timer2);
  }, []);

  return (
    <div className="my-container">
      <PerfectScrollbar
        options={{ minScrollbarLength: 10, scrollYMarginOffset: 7 }}
        ref = {scrollBarRef}           
      >
        {myArray && myArray.map((row, idx) => (
          <Row
            key={idx}
            row={row}
          />
        ))}          
      </PerfectScrollbar>
    </div>

  )
}

I set up the timers in case it didn't render properly right away, as to just give it a wait, but it doesn't work with nor without the timers



Solution 1:[1]

As stated in this github answer, this works

import React, { useRef } from 'react'
import PerfectScrollbar from 'react-perfect-scrollbar'
import './styles.css'

const data = new Array(20).fill(0).map((_, i) => i)

export default function App() {
  const ps = useRef()

  function scrollTop() {
    const curr = ps.current
    if (curr) {
      curr.scrollTop = 0
    }
  }

  return (
    <div>
      <button onClick={scrollTop}>Scroll Top</button>
      <div className="container">
        <PerfectScrollbar containerRef={el => (ps.current = el)}>
          {data.map(e => (
            <div className="item" key={e}>
              {e}
            </div>
          ))}
        </PerfectScrollbar>
      </div>
    </div>
  )
}

Solution 2:[2]

To add more to what @user3808307 shared. In case you have a dynamic data and would like to update a scroll by adjust the height. Use useEffect to render the component.

const scrollRef = useRef<HTMLElement>(null); // I am using typescript
  useEffect(() => {
    if (scrollRef.current) {
      scrollRef.current.scrollTop = 0;
    }
  }, [data]);  // This is your data. Pass it as dependency to tell the scroll that every time there is a new data change please make `scrollTop` to zero.

Let PerfectScrollbar know about it by doing the following

  <PerfectScrollbar containerRef={(el) => { scrollRef.current = el; }}>
      ... // add content here
  </PerfectScrollbar>

I hope folks found it helpful :)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 user3808307
Solution 2 Niyongabo Eric