Hai Tien
Hai Tien

Reputation: 3117

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'.

Upvotes: 75

Views: 263068

Answers (12)

Sabbir Ahmed
Sabbir Ahmed

Reputation: 1704

This should work:

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

EDIT: To update the vertical position every time you scroll, you could utilize event listeners like this (also suggested by Lucas Andrade in a separate answer):

const [scrollYPosition, setScrollYPosition] = React.useState(0);

const handleScroll = () => {
    const newScrollYPosition = window.pageYOffset;
    setScrollYPosition(newScrollYPosition);
};

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

// Now the vertical position is available with `scrollYPosition`
console.log(scrollYPosition)

And here's a bit of trivia:

window.pageYOffset is an alias of window.scrollY property which returns the number of pixels that the document is currently scrolled vertically from the origin, i.e. Y coordinate of the top edge of the current viewport. If the document is not scrolled at all up or down, then scrollY is 0.

Similarly, you can get the number of pixels the document is scrolled horizontally from the origin using scrollX property (window.pageXOffset alias).

Reference: https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY

Upvotes: 35

ABIN GEORGE
ABIN GEORGE

Reputation: 1

Also you can use a npm package to track the user scroll position https://www.npmjs.com/package/react-hook-collections

Upvotes: 0

crystal
crystal

Reputation: 241

Use window.scrollY instead of window.pageYOffset(deprecated).

  const [scrollPosition, setScrollPosition] = useState(0);
  
  useEffect(() => {
    if (typeof window !== "undefined") {
      
      const handleScroll = () => {
        const position = window.scrollY;
        setScrollPosition(position);
      }

      window.addEventListener("scroll", handleScroll);
   
      return () => window.removeEventListener("scroll", handleScroll);
    }
  }, [])

Upvotes: 0

lwdthe1
lwdthe1

Reputation: 1280

Combining some of the other answers, this is exactly what is needed here. Simply use this hook to get the scrollX (horizontal) and scrollY (vertical) positions from the window. It'll be updated as the user scrolls.

/// in useWindowScrollPositions.js

import { useEffect, useState } from 'react'

export const useWindowScrollPositions = () => {

   const [scrollPosition, setPosition] = useState({ scrollX: 0, scrollY: 0 })

   useEffect(() => {
    function updatePosition() {
        setPosition({ scrollX: window.scrollX, scrollY: window.scrollY })
    }

    window.addEventListener('scroll', updatePosition)
    updatePosition()

    return () => window.removeEventListener('scroll', updatePosition)
   }, [])

   return scrollPosition
}

Then call the hook in your function component:

/// in MyComponent.jsx

import { useWindowScrollPositions } from 'path/to/useWindowScrollPositions'

export const MyComponent = () => {
   const { scrollX, scrollY } = useWindowScrollPositions()
   
   return <div>Scroll position is ({scrollX}, {scrollY})</div>
} 

Note that window.pageXOffset and window.pageYOffset, which were used in the other answers from years ago, have been deprecated in favor of window.scrollX and window.scrollY

Upvotes: 10

vancy-pants
vancy-pants

Reputation: 1348

Found this on MDN:

element.scrollHeight - Math.abs(element.scrollTop) === element.clientHeight

Upvotes: 1

Mint
Mint

Reputation: 1059

You can use the native react event listener.

<div onScroll={(e) => console.log("scrolling!", e.target.scrollTop)}>
    <h3>Some huge div</h3>
</div>

Upvotes: 8

Lucas Andrade
Lucas Andrade

Reputation: 4570

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.

Upvotes: 87

Bohdan Yashchuk
Bohdan Yashchuk

Reputation: 181

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;
}

Upvotes: 18

aitbella
aitbella

Reputation: 1095

this repo helped me a lot https://github.com/n8tb1t/use-scroll-position

yarn add @n8tb1t/use-scroll-position

import { useScrollPosition } from '@n8tb1t/use-scroll-position'


useScrollPosition(({ prevPos, currPos }) => {
 console.log(currPos.x)
 console.log(currPos.y)
})

Upvotes: 1

EQuimper
EQuimper

Reputation: 5929

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,
  })
}

Upvotes: 57

Bhojendra Rauniyar
Bhojendra Rauniyar

Reputation: 85545

Like this:

theposition: e.y // or, e.pageY

Or,

theposition: e.clientY - e.currentTarget.getBoundingClientRect().top

Upvotes: 4

Pavittar Singh
Pavittar Singh

Reputation: 55

to get current scroll position you can use

horizontal scrolling amount window.pageXOffset

vertical scrolling amount window.pageYOffset

Upvotes: 3

Related Questions