Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a component show/hide on scroll in react.js

I'm trying to make a footer banner show only when user scrolls down past the header, and hide it when user scrolls up to top. My idea of how to implement this is to add an event listener for scroll event in the top component of the page. Here's my current code. But it doesn't work:

componentDidMount() {
  this.nv.addEventListener('scroll', this.handleScroll);
}

handleScroll(e) {
  if(window.pageYOffset > 50 && window.pageYOffset < 900) {
    console.log('scrolled');
    this.setState({
      showBanner: true,
    });
  } else {
    this.setState({
      showBanner: false,
    });
  }
}

The render method of the top component:

render() {
  return (
    <div ref={elem => this.nv = elem}>
      <Header/>
      <Body
        userInfo={this.props.userInfo}
        history={this.props.history}
      />
      {
        this.state.showBanner && <Banner/>
        || null
      }
    </div>
  )
}

I don't see any logs and the setState is apparently not called when scrolling.

Any suggestion on how I can accomplish the intended goal?

* UPDATE * Changed componentDidMount to add event listener on window, now it's working.

componentDidMount() {
  window.addEventListener('scroll', this.handleScroll);
}
like image 616
NatashaC Avatar asked Jan 19 '18 19:01

NatashaC


1 Answers

The reason is because you are trying to add an event listener to a ref that doesn't exist yet. componentDidMount happens BEFORE the initial render. That means that the ref you assign in render hasn't been set yet.

You can use a ref callback and attach the event listener there:

applyRef = ref => {
  this.vn = ref;
  this.vn.addEventListener('scroll', this.handleScroll);
}
render() {
  return (
    <div ref={this.applyRef}>
      <Header/>
      <Body
        userInfo={this.props.userInfo}
        history={this.props.history}
      />
      {
        this.state.showBanner && <Banner/>
        || null
      }
    </div>
  )
}
like image 134
Chase DeAnda Avatar answered Oct 14 '22 21:10

Chase DeAnda