phileras phileras - 2 months ago 10
Javascript Question

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

I having performance problems with React, basically I have 2 compact menus that appear when the page scroll to x distance from the top. As I see another components of the web application are doing little moves when I scroll, the cause is because they are re-rendering.

To know the distance to the top while a user does a scroll I have a eventlistener on the componentDidMount() and I think that this is causing the problem but I'm not sure, as you know react stable version is pretty new and I'm also new with this technology:

Here is some code, exactly the top bar where are nested components and triggers the compact menu bar to appear when user scolls more than 100px from 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 been investigatin and reading info about the components lifecycle and other performance stuff like this: PURERENDERMIXIN

Do you know a better way to do things to get light web applications and avoid re-rendering on scroll?

Answer

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 cause state change (and re-rendering) only when you pass the scrollTop threshold (100) from one direction or other. Otherwise we don't need to set state at all, thus avoiding render to be called.

Comments