DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • The Complete Tutorial on the Top 5 Ways to Query Your Relational Database in JavaScript - Part 2
  • An Introduction to Type Safety in JavaScript With Prisma
  • 6 Tips to Help You Write Cleaner Code in Node.js
  • React’s Unstoppable Rise: Why It’s Here to Stay

Trending

  • Power BI Embedded Analytics — Part 2: Power BI Embedded Overview
  • Scalable System Design: Core Concepts for Building Reliable Software
  • Scalable, Resilient Data Orchestration: The Power of Intelligent Systems
  • Accelerating AI Inference With TensorRT
  1. DZone
  2. Coding
  3. JavaScript
  4. Optimize Performance and Render Websites Superfast in ReactJS

Optimize Performance and Render Websites Superfast in ReactJS

In order to optimize performance of your React code, you have to make sure that it’s not re-rendering unnecessarily. This is the main reason for bottlenecks.

By 
deven rathore user avatar
deven rathore
·
Dec. 10, 20 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
4.2K Views

Join the DZone community and get the full member experience.

Join For Free

To optimize the performance of your React code, you have to make sure that it’s not re-rendering unnecessarily. This is the main reason behind performance bottleneck. Use these tips to improve your codebase and make your website super-fast:

  1. Avoid unnecessary code re-rendering.
  2. Keep your code files short and break them into components.
  3. Use minified production build.
  4. Remove console logs from production code.
  5. For big tables, render a few rows and columns at a time (like FlatList in React Native).
  6. Do not mutate state object.

Let’s discuss all these points, one at a time. Buckle up.

Avoid Unnecessary Code Re-rendering

To avoid re-rendering, we use useCallback or useMemo in functional components and shouldComponentUpdate in class-based components. But frankly, we should avoid using these functions unless and until we are getting serious problems like the unresponsiveness of browsers.

Let me tell you how it all works. Suppose I bought a pair of shoes and I don’t want them to be dirty. So, I started walking with shoe covers on them. When I reach home, I throw away the covers, and my shoes are clean. I am happy. But in this whole process, I increased my expenditure on covers and the trouble of putting them all the time when I have to move out.

Now, it's actually a balance between making my shoes dirty and increasing my troubles. If the dirt is light, why not simply clean the shoe with water? Why would I increase my expenditures on covers?

Performance optimization works in the same way. All the methods come with their own overheads. useMemo is good when the task is computationally heavy; otherwise, let the system compute when it is required.

Why Shouldn’t We Use useMemo Frequently?

There are some excellent reasons for that:

  1. It comes with its own overhead.
  2. It makes your code unnecessarily complex for your teammates.
  3. Since it caches the results (memoization), the garbage collector won’t run on it and end up using memory for no reason. We are saving computations but sacrificing memory. But is the computation needing to be saved in our code? That decides whether to use it or not.

Some re-rendering is fine but wasteful rendering should be avoided. Look at these examples:

JavaScript
 




xxxxxxxxxx
1
15


 
1
const [firstName, setFirstName] = useState('');
2
const [lastName, setLastName] = useState('');
3

          
4
return (
5
    <div>
6
      <div>
7
        Enter First Name: <input type="text" value={firstName} onChange={(e) => setFirstName(e.target.value)} /> &nbsp;&nbsp;&nbsp;
8
        Enter Last Name: <input type="text" value={lastName} onChange={(e) => setLastName(e.target.value)} />
9
      </div>
10
      <div>
11
        First Name: {firstName} &nbsp;&nbsp;&nbsp;
12
        Last Name: {lastName}
13
      </div>
14
    </div>
15
);



In this code, I am setting up two input fields for first name and last name. Also, the values will be displayed on the next div block. Whenever we change any input field, the whole section will be re-rendered. Although we do not want to render the last name input field and display field, that’s absolutely fine. We should not over-optimize performance. Check out this code demo:


This demo shows how much time it is taking to render the section. In my case, it was taking 32.72 milliseconds.

Let’s over-optimize this code and check the performance:

JavaScript
 




xxxxxxxxxx
1
31


 
1
const [firstName, setFirstName] = useState('');
2
const [lastName, setLastName] = useState('');
3

          
4
const FirstName = React.memo(({firstName}) => {
5
    return (
6
      <div style={{marginBottom:'10px'}}>
7
        First Name: {firstName}
8
      </div>
9
    )
10
})
11

          
12
const LastName = React.memo(({lastName}) => {
13
    return (
14
      <div style={{marginBottom:'10px'}}>
15
        Last Name: {lastName}
16
      </div>
17
    )
18
})
19

          
20
return (
21
    <div>
22
      <div>
23
        Enter First Name: <input type="text" value={firstName} onChange={(e) => setFirstName(e.target.value)} />{&nbsp;&nbsp;&nbsp;}
24
        Enter Last Name: <input type="text" value={lastName} onChange={(e) => setLastName(e.target.value)} />
25
      </div>
26
      <div>
27
        <FirstName firstName={firstName} />
28
        <LastName lastName={lastName} />
29
      </div>
30
    </div>
31
);



I have separated the display labels into individual components and memoize them using the memo function. In this case, the labels won’t re-render unless you change them using their respective input fields. Let’s check the time taken in the demo:


In my case, it is taking 37.7 milliseconds. It’s essentially the same time which it was taking before memoization.

useMemo and memo are two different things. Former is a hook and latter is a function. useMemo is used to memoize computations while memo wraps over the component to decide whether to re-render or not.

Where Can useMemo Optimize Performance?

When computations are heavy, and we are worried more about it than re-rendering. Look at this code:

Warning: It’s a computation heavy code so use it with caution.

 

JavaScript
 




xxxxxxxxxx
1
34


 
1
  const [firstName, setFirstName] = React.useState('');
2
  const [lastName, setLastName] = React.useState('');
3
  const [num, setNum] = React.useState(50000000);
4

          
5
  const heavyNumber = (num) => {
6
    let heavyNum = 0;
7
    for(let i=0; i<num; i++){
8
      heavyNum += num;
9
    }
10
    return heavyNum;
11
  }
12
 
13
  return (
14
    <div>
15
      <div>
16
        Enter First Name: <input type="text" value={firstName} onChange={(e) => setFirstName(e.target.value)} /> <br />
17
      Enter Last Name: <input type="text" value={lastName} onChange={(e) => setLastName(e.target.value)} /> <br />
18
      Enter Some Number: <input type="number" value={num} onChange={(e) => setNum(parseInt(e.target.value) < 50000000 ? parseInt(e.target.value): num)} />
19
      </div>
20
      <div>
21
        First Name: {firstName} <br />
22
        Last Name: {lastName} <br />
23
        Computation Heavy Number: {heavyNumber(num)}
24
      </div>
25
      <div style={{marginTop: '30px'}}>
26
        Time Spent in Rendering ~ {timeDiff} milliseconds
27
      </div>
28
      <div style={{marginTop: '30px'}}>
29
        Type fast in input field (first name or last name) and check the time spent
30
      </div>
31
    </div>
32
  );
33

          
34

          



Here the rendering will lag. This is because the heavyNumber will be calculated on each render, and that’s unnecessary. Calculate the time it takes to render if you change First Name or Last Name only:


It is taking nearly ~120 milliseconds, and if you type longer then it may get unresponsive. Now let's optimize its performance by using useMemo

JavaScript
 




x
30


 
1
  const [firstName, setFirstName] = React.useState('');
2
  const [lastName, setLastName] = React.useState('');
3
  const [num, setNum] = React.useState(50000000);
4

          
5
  const heavyNumber = React.useMemo(() => {
6
    let heavyNum = 0;
7
    for(let i=0; i<num; i++){
8
      heavyNum += num;
9
    }
10
    return heavyNum;
11
  }, [num])
12

          
13
  <div>
14
      <div>
15
        Enter First Name: <input type="text" value={firstName} onChange={(e) => setFirstName(e.target.value)} /> <br />
16
      Enter Last Name: <input type="text" value={lastName} onChange={(e) => setLastName(e.target.value)} /> <br />
17
      Enter Some Number: <input type="number" value={num} onChange={(e) => setNum(parseInt(e.target.value) < 50000000 ? parseInt(e.target.value): num)} />
18
      </div>
19
      <div>
20
        First Name: {firstName} <br />
21
        Last Name: {lastName} <br />
22
        Computation Heavy Number: {heavyNumber}
23
      </div>
24
      <div style={{marginTop: '30px'}}>
25
        Time Spent in Rendering ~ {timeDiff} milliseconds
26
      </div>
27
      <div style={{marginTop: '30px'}}>
28
        Type fast in input field (first name or last name) and check the time spent
29
      </div>
30
    </div>



In this code, if you change the first name and last name input fields, then you will not find any unresponsiveness or lag in rendering. If you change the number field only then, it will re-compute the value of the heavyNumber variable. Also, it will store the previously computed values. So, if you enter the number 5000, then it will compute heavyNumber. If you change it to 5003, it will again calculate heavyNumber for it. But if you change it back to 5000, then it won’t recalculate. Else it will use the previously calculated number, which is stored already:


Refactor and Break Code into Components

Refactoring a code is important in terms of both code optimization and maintenance. All the reusable components could be separated. In React, we can use refactoring to prevent re-rendering.

Although we have to keep it in balance, sometimes we end up making a lot of small components that are hard to maintain.

Remember, if you got something as an option and not built in, then either it is for maintaining backward compatibility or that “something” is not ideal for general cases.

This code will show you how refactoring can prevent re-rendering:

JavaScript
 




xxxxxxxxxx
1
27


 
1
const FirstName = () => {
2
    const [firstName, setFirstName] = useState('');
3
    return (
4
        <div style={{marginBottom: '10px'}}>
5
            Enter First Name: <input type="text" value={firstName} onChange={(e) => setFirstName(e.target.value)} /><br />
6
            First Name: {firstName}
7
        </div>
8
    );
9
}
10

          
11
const LastName = () => {
12
    const [lastName, setLastName] = useState('');
13
    return (
14
        <div style={{marginBottom: '10px'}}>
15
            Enter Last Name: <input type="text" value={lastName} onChange={(e) => setLastName(e.target.value)} /><br />
16
            Last Name: {lastName}
17
        </div>
18
    );
19
}
20

          
21

          
22
return (
23
    <div>
24
      <FirstName />
25
      <LastName />
26
    </div>
27
);



This example is the same as the above ones. Here I have separated the input fields with their respective display labels in different components. The first name data is in <FirstName /> component and last name data in <LastName /> component.

Since the components are different, they do not share state with each other. Changing the first name will not render anything belonging to the last name. Check out the demo:


Use Minified Production Build

Do not use debug code for your production server. Its because all the files are bulky, and a lot of debugging related operations going on in the background.

If you are using the create-react-app command for creating your application, then run npm buildand it will generate a production-ready build for you. Otherwise, you can directly import the script and css files hosted on unpkg.com cdn:

https://unpkg.com/react@17/umd/react.production.min.js

https://unpkg.com/react-dom@17/umd/react-dom.production.min.js

Remove Console Logs from Production Code

While developing our application, we use a lot of console properties like logs, error, debug etc. But writing at the console is also overhead for your web application. Its fine during development but doesn’t make sense in production code. In fact, it will reveal way too much information about your application to the end users.

To remove all the console logs from your production build automatically, you can use this Babel Plugin.

Lazy Rendering for Big Tables

You may face rendering issues if your tables are pretty big. We can handle this by lazily rendering the tables like we do in FlatList in React-Native.

There is a library, React-Window, which helps in virtualizing the large lists and lazily render.

Do not Mutate State Object

Mutation of state objects is a bad idea and it could lead to the buggy code. Sometimes this impacts the performance and we look at all the wrong places to optimize it. Always change the state using useState or setState functions only.

This is the wrong practice:

JavaScript
 




x


 
1
state = {
2
  name : {first: '', last: ''},
3
}
4

          
5
this.state.name.first = 'Captain';
6
this.state.name.last = 'America';



What is wrong here? We are mutating the state directly. This will not update the DOM. React has provided the setState and useState functions to understand when its time to render.

Let’s see this in action:


The correct way is using setState and useState:

JavaScript
 




x


 
1
state = {
2
  name : {first: '', last: ''},
3
}
4

          
5
const nameTemp = {...this.state.name};
6
nameTemp.first = 'Captain';
7
nameTemp.last = 'America';
8
this.setState({name: nameTemp});



Here we are using the three-dot notation ... of ES6 to copy the name object in the state. In this codenameTemp will hold the copy of the name object and not the reference. So, this.state.name will not be equal to nameTemp. Any changes you make in a nameTemp object will not reflect in this.state.name. Then we call this.setState to render with new values.

These are some of the performance optimization strategies you can adopt to make your application fast and maintainable. I hope you learned something. Please share your views in the comment section.

code style optimization Database application Production (computer science) JavaScript Object (computer science) React (JavaScript library) Console (video game CLI) IT

Published at DZone with permission of deven rathore. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • The Complete Tutorial on the Top 5 Ways to Query Your Relational Database in JavaScript - Part 2
  • An Introduction to Type Safety in JavaScript With Prisma
  • 6 Tips to Help You Write Cleaner Code in Node.js
  • React’s Unstoppable Rise: Why It’s Here to Stay

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!