GAZAR

Principal Engineer | Mentor

Optimizing React Components

Optimizing React Components

Time to talk about more optimization than just simply writing a react component, what would you do? and what are the options available?

I have a few articles about the performance of the app and how to make it better like these:

- Refactoring Bad Smells in Code

- Optimizing JavaScript Event Listeners for Performance

But in this article, I am focusing on just one function

1. Write a function instead of a class

Simple and I think if you have been around for a while, you know how to use hooks and solve your problems, I have a full article explaining hooks here.

That means instead of writing:

class ProfilePage extends React.Component {
  showMessage = () => {
    alert('Followed ' + this.props.user);
  };
  handleClick = () => {
    setTimeout(this.showMessage, 3000);
  };

  render() {
    return <button onClick={this.handleClick}>Follow</button>;
  }
}

You can start writing:

function ProfilePage(props) {
  const showMessage = () => {
    alert('Followed ' + props.user);
  };

  const handleClick = () => {
    setTimeout(showMessage, 3000);
  };

  return (
    <button onClick={handleClick}>Follow</button>
  );
}

2. Using useCallback and useMemo

These two hooks will prevent functions to be re-instanced again and that helps your app to have a better performance, by just simply wrapping your functions inside these two.

const increment = useCallback(() => {
  setCount(count + 1)
}, [count])

or

const memoizedValue = useMemo(() => handleExpsValue(a, b), [a, b]);

3. Use React Fragments instead of Divs

This is another concept that might seem unnecessary but eventually, it removes the hierarchy of divs in the DOM, and the fewer things in DOM, you’ll be having a performant product.

You can have it like this:

<React.Fragment>                 
   <h1>Comment Title</h1>                 
   <p>comments</p>                
   <p>comment time</p>             
</React.Fragment>

or even easier:

<>                 
   <h1>Comment Title</h1>                 
   <p>comments</p>                
   <p>comment time</p>             
</>

4. Avoid Inline Function Definition in the Render Function

Defining a function in render method slows than your component by re-rendering each time, the better way is to separate the function and define it somewhere else, you can also go to use useCallback , too.

so it means instead of:

comments.map((comment)=>{                
   return <Comment 
             onClick={(e)=>{                         
                this.setState({selectedCommentId:comment.commentId})
             }} 
             comment={comment} 
             key={comment.id} />            
})

It’s better to develop it like this:

const onCommentClick = (commentId)=>{
   this.setState({selectedCommentId:commentId})
}

render(){
   const { comments } = this.state;
   return (
   comments.map((comment)=>{
      return <Comment 
                onClick={this.onCommentClick}
                comment={comment} 
                key={comment.id}/>
   }))
}

Note: of course it is even better to write a function instead of a class as point 1 in this article is describing.

5. Avoid Async Initialization in componentWillMount

Another common thing can be using component async, await in componentWillMount , that slows your component significantly. Just do not do it 😱

6. CSS Animations Instead of JS Animations

Pointing an obvious, do not use JavaScript animations in your component to move something on the page, the best way is to use CSS animations and if you are pressured to do more, try to just do it with add or removing a class.

7. Optimize your EventListeners

I have a full article of defining event listeners here, however, the other thing which is important is to remove the event listener from DOM, if your component is unmounted.

You can easily do it like this:

const MyComponent = () => {
  useEffect(() => {
     window.addEventListener('mousemove', () => {});
     return () => {
       window.removeEventListener('mousemove', () => {})
     }
  }, [])

  return (
    <div />
  );
}

8. Use Virtualization Long Lists

The other new method of implementing those long lists, tables or scrolling pages, is to render whatever is just visible on the page.

One of the old and good libraries to do that is:

https://github.com/bvaughn/react-virtualized

9. Do not use random keys or just not unique keys on your components

Since keys are being used to identify your elements on DOM, using random keys will generate and mount and unmount the component multiple times.

And good to mention that, if it is just {index} or something similar, it won’t be unique, and react will be confused about replacing this component.

So make sure you are using a unique key for your component.

10. Using shouldComponentUpdate

If you are writing class components, and you know that your component when needs to be updated, it’s better to specify it here in shouldComponentUpdate , which helps to prevent unneeded renders.

Easy as this:

shouldComponentUpdate(nextProps, nextState) {
    return nextProps.id !== this.props.id;
}

Conclusion

React might be an awesome tool to develop frontend, but if you keep doing smelly codes, you are not using its potentials.

keep in mind, whenever you are writing new code or even refactoring to follow these steps.