Avoid re-rendering on scroll and increase performance in React web app

I'm having trouble working with React, basically I have 2 compact menus that pop up when the page is scrolled to x distance from the top. As I can see, other components of the web application take small steps when scrolling, the reason is they are being redrawn.

To find out the distance to the top while the user is scrolling, I have an eventlistener on componentDidMount () and I think this is causing the problem, but I'm not sure as you know the stable version is pretty new and I also new to this technology:

Here is some code, exactly the top bar that contains the nested components, and triggers the compact menu bar when the user scans over 100 pixels from the top:

export default class AppTopBar extends Component {
    constructor (props){
        super(props);
        this._bind("_handleOnScrollDocument");
        this.state = {
            StatusBar: false
        }
    }

    componentDidMount() {
        if (process.env.BROWSER) {
            document.addEventListener("scroll", (e) => this._handleOnScrollDocument(e), true);
        }
    }

    _handleOnScrollDocument(e) {
        if (e.target.body.scrollTop > 100) {            
            this.setState({ StatusBar: true }); 
        } else {
            this.setState({ StatusBar: false });
        }
    }

    render() {
        return (
            <div className="aui-core-apptopbar">
                <StatusBar companies={this.props.companies} compactMenuItems={this.props.compactMenuItems} StatusBar={this.state.showCompactStatusBar}/>
                <StatusBar companies={this.props.companies} userOptions={this.props.userOptions} compactMenuItems={this.props.compactMenuItems}/>
                <MainNavBarView menuItems={this.props.menuItems}/>
            </div>
        );
    }
}

      

I have researched and read information about component lifecycle and other features like: PURERENDERMIXIN

Do you know it's better to do something to get lightweight web apps and avoid re-rendering on scroll?

+3


source to share


3 answers


Let's say you create a local variable flag

for your class. And then:

_handleOnScrollDocument(e) {
  let newFlag = (e.target.body.scrollTop > 100);
  if (flag !== newFlag) {
    this.setState({showCompactStatusBar: newFlag});
    flag = newFlag;
  }
};

      



This will only change the state (and re-render) when the scrollTop (100) threshold is passed in one direction or another. Otherwise, we don't need to set the state at all while avoiding render

.

+5


source


The "built-in" solution is to use a method shouldComponentUpdate

that allows you to compare the current props

and state

component to the input props

and state

then, if you choose:



_handleOnScrollDocument(e) {
    // set the state no matter what
    this.setState({
        showCompactStatusBar: e.target.body.scrollTop > 100
    });
},

shouldComponentUpdate(newProps, newState) {
    // only render if the state has changed
    return this.state.showCompactStatusBar !== newState.showCompactStatusBar;
}

      

+2


source


I had a scroll event on a component inside my page where the overflow: auto

CSS rule was . I hooked up a scroll event listener to this component as it was targeted for in this blog post . However, setting the last scroll position to a state can severely hinder performance.

So instead, I defined the last position inside the class constructor and changed it there, and avoided re-rendering on every scroll.

constructor(props){
  super(props)
  this.state = { scrollDirection: 'up' }
  this.lastY = 0
}

      

I would only change state if direction changed.

handleListScroll(event){
  const Y = event.currentTarget.scrollTop
  const lastY = this.lastY
  if (Y > lastY) {
    scrollDirection = 'down'
    if (this.state.scrollDirection === 'up') {
      this.setState({
        scrollDirection,
      })
    }
  }
  if (Y < lastY) {
    scrollDirection = 'up'
    if (this.state.scrollDirection === 'down') {
      this.setState({
        scrollDirection
      })
    }
  }
  this.lastY = Y
}

      

0


source







All Articles