React React Scroll toTop

Developed by: Donald Boulton Living in OKC. Follow Him on Twitter.🙌 0
Apr 22, 20194 min readReact, toTop, Scroll  Category:  Tech

Scroll toTop or Bottom

🔝 Have you tried Scroll to the top of the page react module's, I have and all of them use the .window function to go to top. Which does not work in React without a work around.

import Scroll from 'react-scroll'

Then tell React that, window !== undefined.

// eslint-disable-next-line valid-typeof
if (typeof window !== undefined) { require('react-scroll') }

Such as the errors I got from react-scroll, and the workaround I used, "Which Works", but I did not like the implementation

So I came up with my own digging through React Repos. With React we can use handleScroll and window.pageYOffset to go to top or bottom of the page or anything.

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

// and then use handleScroll and window.pageYOffset to go to top or bottom

const scroll = ({ mode, to }) =>
    window[`scroll` + mode]({ top: to, behavior: `smooth` })

  const handleScroll = () => {
    if (window.pageYOffset > showBelow) {
      if (!show) setShow(true)
    } else {
      if (show) setShow(false)
    }
  }

styled icon styledArrow

src/components/Scroll
import React, { useState, useEffect } from 'react'import { Arrow } from './styles'
const Scroll = ({
  direction = `up`,  by,
  to,
  showBelow,
  className,
  size = `1.7em`,
}) => {
  if (![`up`, `down`].includes(direction))
    throw TypeError(
      `Scroll component's direction prop must be either 'up' or 'down'`
    )
  if (to && (typeof to !== `number` || to <= 0))
    throw TypeError(`Scroll component's to prop must be a positive number`)
  if (by && typeof by !== `number`)
    throw TypeError(`Scroll component's by prop must be a number`)

  const [show, setShow] = useState(showBelow ? false : true)

  const scroll = ({ mode, to }) =>
    window[`scroll` + mode]({ top: to, behavior: `smooth` })

  const handleScroll = () => {
    if (window.pageYOffset > showBelow) {
      if (!show) setShow(true)
    } else {
      if (show) setShow(false)
    }
  }

  const handleClick = () => {
    if (to) scroll({ mode: `To`, to: to * window.innerHeight })
    else if (by) scroll({ mode: `By`, to: by * window.innerHeight })
    else if (direction === `up`) scroll({ mode: `To`, to: 0 })
    else scroll({ mode: `To`, to: document.body.scrollHeight })
  }

  useEffect(() => {
    if (showBelow) {
      window.addEventListener(`scroll`, handleScroll)
      return () => window.removeEventListener(`scroll`, handleScroll)
    }
  })

  const arrowProps = { show, direction, className, size }
  return <Arrow onClick={handleClick} {...arrowProps} />
}

export default Scroll

styles.js Code

src/components/Scroll/styles
import styled from 'styled-components'
import { ArrowDownCircle as Down } from '@styled-icons/feather/ArrowDownCircle'
import { ArrowUpCircle as Up } from '@styled-icons/feather/ArrowUpCircle'

export const Arrow = styled(Down).attrs(({ direction, size }) => ({
  as: direction === `up` && Up,
  size,
}))`
  ${({ theme, show, size }) => `
  z-index: 2;
  background: ${theme.darkOrange};
  color: ${theme.textColor};
  border-radius: 50%;
  transition: ${theme.shortTrans};
  position: fixed;
  bottom: 2.5em;
  opacity: ${show ? 1 : 0};
  visibility: ${show ? `visible` : `hidden`};
  :hover {
    transform: scale(1.15);
    background: ${theme.orange};
  }
  right: calc(1vw - ${size} / 1);`}
`

Add Scroll

src/components/Scroll
  <Scroll
    showBelow={1500}
    css='position: fixed; right: 1.3em; bottom: 1.3em;'
  />

Scroll Down

src/components/ScrollDown
import React, { useState, useEffect } from 'react'
import { Arrow } from './styles'

const ScrollDown = ({
  direction = `down`,
  by,
  to,
  showBelow,
  className,
  size = `1.7em`,
}) => {
  if (![`up`, `down`].includes(direction))
    throw TypeError(
      `Scroll component's direction prop must be either 'up' or 'down'`
    )
  if (to && (typeof to !== `number` || to <= 0))
    throw TypeError(`Scroll component's to prop must be a positive number`)
  if (by && typeof by !== `number`)
    throw TypeError(`Scroll component's by prop must be a number`)

  const [show, setShow] = useState(showBelow ? false : true)

  const scroll = ({ mode, to }) =>
    window[`scroll` + mode]({ top: to, behavior: `smooth` })

  const handleScroll = () => {
    if (window.pageYOffset > showBelow) {
      if (!show) setShow(true)
    } else {
      if (show) setShow(false)
    }
  }

  const handleClick = () => {
    if (to) scroll({ mode: `To`, to: to * window.innerHeight })
    else if (by) scroll({ mode: `By`, to: by * window.innerHeight })
    else if (direction === `up`) scroll({ mode: `To`, to: 0 })
    else scroll({ mode: `To`, to: document.body.scrollHeight })
  }

  useEffect(() => {
    if (showBelow) {
      window.addEventListener(`scroll`, handleScroll)
      return () => window.removeEventListener(`scroll`, handleScroll)
    }
  })

  const arrowProps = { show, direction, className, size }
  return <Arrow onClick={handleClick} {...arrowProps} />
}

export default ScrollDown

Scroll styles.js

src/components/ScrollDown/styles
export const Arrow = styled(Up).attrs(({ direction, size }) => ({
  as: direction === `down` && Down,
  size,
}))`
  ${({ theme, show, size }) => `
  z-index: 2;
  background: ${theme.darkOrange};
  color: ${theme.textColor};
  border-radius: 50%;
  transition: ${theme.shortTrans};
  position: fixed;
  top: 4.5em;
  opacity: ${show ? 1 : 0};
  visibility: ${show ? `visible` : `hidden`};
  :hover {
    transform: scale(1.15);
    background: ${theme.orange};
  }
  right: calc(1vw - ${size} / 1);`}
`

Post Template

Only my post's are long enough to need scroll down

add
  <ScrollDown
    direction='down' to={15}
    showAbove={1500}
    css='position: fixed; right: 1em; top: 4.5em;'
  />

Scroll down is visible at the top of the page and is fixed. I think its cool and somewhat original. Not static like the Netlify build page has scroll to bottom of the build log or back to top which is pretty Cool.



Slack

Bring your team together with Slack, Work collaboration hub.

MailChimp Newsletters
MailChimp Newsletters

Enjoyed this post? Subscribe!
Css Tricks

Front-End UI, Javascript & Functions, HTML Tips, and More!