0

I have a stateful component which has a scroll event listener like this

import React, { Component } from 'react'
import { withRouter } from 'react-router'
import AppDetailPageUI from './AppDetailPageUI.js'


class AppDetailPageSF extends Component {
  constructor(props) {
    super(props);
    this.state = {
        scrolledDown:false,
    };

    this.handleScroll = this.handleScroll.bind(this);
  }

  render() {
    return (
      <AppDetailPageUI

        scrolledDown={this.state.scrolledDown}
      />
    );
  }


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

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

  handleScroll(event)  {

    if (window.scrollY === 0 && this.state.scrolledDown === true) {
      this.setState({scrolledDown: false});
    } 
    else if (window.scrollY !== 0 && this.state.scrolledDown !== true) {
      this.setState({scrolledDown: true});
    }
  }

}

export default withRouter(AppDetailPageSF)

This works perfectly fine.But i want to use handleScroll method in many statefull components, and including the same method in every component is not a good practice.

so this is what i tried instead, I created another HandleScrollUtil function something like this

const HandleScrollUtil = {
    handleScroll: function(component) {

    if (window.scrollY === 0 && component.state.scrolledDown === true) {
        component.setState({scrolledDown: false});
    } 
    else if (window.scrollY !== 0 && component.state.scrolledDown !== true) {
        component.setState({scrolledDown: true});
    }
  }
}

export default HandleScrollUtil

and then i tried calling this method by passing this reference something like this

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

  componentWillUnmount() {
    window.removeEventListener('scroll',  HandleScrollUtil.handleScroll(this));
  }

But it does not seem to work now.

1 Answer 1

1

Only respective component can deal with its state, you can create handler inside the AppDetailPageSF component something like

setScrollDownHandler = (event,scrollValue) =>{
 this.setState({scrolledDown: scrollValue});
}

then you can pass this handler down to any component has a prop, this is the right way to it.

Code to update the State must be in the same component, all we could do it is create a hander to deal with it and pass that handler to places where we would like to update it from.

Solution is a Higher Order Component

I would recommend using a HOC like this, it can be wrapped to any component you are going to use.

import React, { Component } from 'react';


const withScrollHandler = (WrappedComponent) => {
    return class extends Component {

        componentDidMount() {
              this.props.setScrollDownHandler();
        }

        componentWillUnmount() {
              this.props.setScrollDownHandler();
        }

        render () {
            return (
                <div>
                    <WrappedComponent {...this.props} />
                </div>
            );
        }
    }
}

export default withScrollHandler;
Sign up to request clarification or add additional context in comments.

1 Comment

But i can only pass this handler only if there is parent-child relationship between component. I want to have this handleScroll method in many components which has no relationship with one another, so is it a good practice to include the same method in every component as it will lead to duplicate code?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.