16

How to add class in element on scroll React js, I want to add class in on scroll and remove that class if on top of the page.

import React from "react"
import { Link } from "react-router"
import { prefixLink } from "gatsby-helpers"
import Helmet from "react-helmet"
import { config } from "config"

module.exports = React.createClass({
  propTypes() {
    return {
      children: React.PropTypes.any,
    }
  },
  render() {
  window.addEventListener('scroll', (event) => {

    });
    return (
      <div>
        <header className="header">
          <div className="top-bar">
            <span><a href="tel:6788272782">678-827-2782 </a></span>
            <span><a href="mailto:hellohello@knotel.com"> hellohello@knotel.com</a></span>
            <button>Login</button>
          </div>
        </header>
        {this.props.children}
      </div>
    )
  },

})
harry
  • 451
  • 2
  • 5
  • 17

4 Answers4

31

If you want to use React Hooks in 2020 stateless component

const [scroll, setScroll] = useState(false);
 useEffect(() => {
   window.addEventListener("scroll", () => {
     setScroll(window.scrollY > 50);
   });
 }, []);

and use it anywhere in your code

className={scroll ? "bg-black" : "bg-white"}

setScroll(window.scrollY > 50); here 50 specify the height.

ZiaUllahZia
  • 1,072
  • 2
  • 16
  • 30
17

Use state to manage classnames and update state in the scroll event. Also, you should move the scroll event binding into the componentDidMount function instead of render.

import React from "react"
import { Link } from "react-router"
import { prefixLink } from "gatsby-helpers"
import Helmet from "react-helmet"
import { config } from "config"

module.exports = React.createClass({
  propTypes() {
    return {
      children: React.PropTypes.any,
    }
  },
  componentDidMount(){
      window.addEventListener('scroll', () => {
         let activeClass = 'normal';
         if(window.scrollY === 0){
             activeClass = 'top';
         }
         this.setState({ activeClass });
      });
  }
  render() {
    return (
      <div>
        <header className="header">
          <div className={`top-bar ${this.state.activeClass}`}>
            <span><a href="tel:6788272782">678-827-2782 </a></span>
            <span><a href="mailto:hellohello@knotel.com"> hellohello@knotel.com</a></span>
            <button>Login</button>
          </div>
        </header>
        {this.props.children}
      </div>
    )
  },

})
Chase DeAnda
  • 15,963
  • 3
  • 30
  • 41
  • 4
    @harry dont forget to removeEventListener in componentWillUnmount too! componentWillUnmount() { window.removeEventListener('scroll'); } – Hadnazzar Sep 17 '18 at 09:35
0
import React, { useState, useEffect } from "react"
import { Link } from "react-router"
import { prefixLink } from "gatsby-helpers"
import Helmet from "react-helmet"
import { config } from "config"

export default function Header(props) {
  const [scroll, setScroll] = useState(false)
  useEffect(() => {
    window.addEventListener("scroll", () => {
      setScroll(window.scrollY > 10)
    })
  }, [])
  return (
    <header className={scroll ? "main-header scrolled" : "main-header"}>
</header>
  )
}
0

One more variant with hooks and cleanup to avoid memory leaks, if the browser is not handled it properly.

const [isScrollValueMoreThanHeaderHeight, setIsScrollValueMoreThanHeaderHeight] = useState(false);

//here 96(px) - height of current header

useEffect(() => {
    const handleScroll = () => {
        setIsScrollValueMoreThanHeaderHeight(window.scrollY > 96);
    }
    window.addEventListener('scroll', handleScroll)
    return () => window.removeEventListener('scroll', handleScroll);
},[])

And then used it in a ternary way to change class

className={isScrollValueMoreThanHeaderHeight ? "class1" : "class2"}
Griha Mikhailov
  • 655
  • 1
  • 9
  • 16