Get scroll position with Reactjs

I use reactjs and want to handle scroll with click event.

Firstly, I rendered list of posts with componentDidMount.

Secondly, by click event on each post in list, It will display post detail and scroll to top (because I put post detail to top position of page).

Thirdly, by clicking "close button" in post detail, it will return previous list of posts but I want website will scroll to exactly to position of clicked post.

I use like this:

Click event to view post detail:

inSingle = (post, e) => {
   this.setState({
        post: post,
        theposition: //How to get it here?
   });
   window.scrollTo(0, 0);
}

I want to get state of theposition then I can do scroll exactly to position of clicked post by 'Close event'.


You can use event listener in react like you will use in other js framework or library.

componentDidMount() {
  window.addEventListener('scroll', this.listenToScroll)
}

componentWillUnmount() {
  window.removeEventListener('scroll', this.listenToScroll)
}

listenToScroll = () => {
  const winScroll =
    document.body.scrollTop || document.documentElement.scrollTop

  const height =
    document.documentElement.scrollHeight -
    document.documentElement.clientHeight

  const scrolled = winScroll / height

  this.setState({
    theposition: scrolled,
  })
}

In case you need to keep on track of the scroll position, you can use react hooks to do so, that way it's possible to check the scroll position any time you need it:

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

...
// inside component:

const [scrollPosition, setScrollPosition] = useState(0);
const handleScroll = () => {
    const position = window.pageYOffset;
    setScrollPosition(position);
};

useEffect(() => {
    window.addEventListener('scroll', handleScroll, { passive: true });

    return () => {
        window.removeEventListener('scroll', handleScroll);
    };
}, []);

In this case useEffect will behavior similar to componentDidMount, it will fire once the component has rendered, but also in every render, as Jared Beach commented bellow: "window.addEventListener is smart enough to discard subsequent calls with the same parameters". . Make sure to return the cleanup function, similar to what you'd do in componentWillUnmount.


This should work:

this.setState({
    post: post,
    theposition: window.pageYOffset
});

import React, { useLayoutEffect, useState } from 'react';

export default function useWindowPosition() {
  const [scrollPosition, setPosition] = useState(0);
  useLayoutEffect(() => {
    function updatePosition() {
      setPosition(window.pageYOffset);
    }
    window.addEventListener('scroll', updatePosition);
    updatePosition();
    return () => window.removeEventListener('scroll', updatePosition);
  }, []);
  return scrollPosition;
}