5 Reasons Your React App is Slow

Earl Red
DevOps.dev
Published in
4 min readApr 11, 2023

--

As your React app grows, you might notice that it’s not as fast as it used to be. In this article, we will discuss five items you should investigate when your React app’s performance starts to slow down, along with practical examples to help you address these issues.

1. Rendering

One of the primary causes of slow React apps is the inefficient rendering of components. React uses a virtual DOM to compare the current and new state of the app and only updates the real DOM when necessary. However, if components are re-rendered unnecessarily, it will cause performance issues.

Example: Suppose you have a List component that renders a list of Item components. If the list updates frequently but individual items rarely change, you can use React.memo to prevent unnecessary re-renders of the Item component.

const Item = React.memo(function Item({ text }) {
return <li>{text}</li>;
});

function List({ items }) {
return (
<ul>
{items.map(item => (
<Item key={item.id} text={item.text} />
))}
</ul>
);
}

2. Bundle Size and Assets

A large bundle size can slow down the initial loading time of your React app. This can be caused by including large libraries, excessive use of inline styles, or not optimizing images and other assets.

Example: Use code-splitting to break down your app into smaller chunks, so that only the necessary code is loaded when needed. You can use React.lazy() to load components only when they are required.


import React, { lazy, Suspense } from ‘react’;

const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<div>
<Suspense fallback={<div>Loading…</div>}>
<HeavyComponent />
</Suspense>
</div>
);
}

3. Main Thread

JavaScript runs on a single thread, which means long-running tasks can block the main thread and make the app unresponsive. Utilize techniques like debouncing, throttling, and web workers to prevent blocking the main thread.

Example: Suppose you have a search input that triggers an API call on every input change. You can use debouncing to delay the API call until the user stops typing.


import { useState, useEffect } from ‘react’;
import debounce from ‘lodash.debounce’;

function Search() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const searchApi = async (searchTerm) => {
// API call implementation
};
const debouncedSearchApi = debounce(searchApi, 300);
useEffect(() => {
if (query) {
debouncedSearchApi(query);
} else {
setResults([]);
}
}, [query]);
return (
<div>
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
{/* Render search results */}
</div>
);
}

4. State Management

Complex state management can lead to performance issues if not handled correctly. Large applications with poorly managed state can become slow and difficult to maintain.

Example: Use a state management library like Redux to simplify state updates and avoid unnecessary re-renders.


// actions.js
export const increment = () => ({
type: ‘INCREMENT’,
});

// reducer.js
const counter = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
default:
return state;
}
};
// App.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment } from './actions';
function App() {
const count = useSelector((state) => state.counter);
const dispatch = useDispatch();
return (
<div>
<button onClick={() => dispatch(increment())}>Increment</button>
<p>Count: {count}</p>
</div>
);
}

5. Large Lists

Rendering large lists of items in a React app can cause slow performance. Virtualization libraries like react-window or react-virtualized can help improve performance by only rendering the items currently visible on the screen.

Example: Use react-window to efficiently render a large list of items.


import React from ‘react’;
import { FixedSizeList as List } from ‘react-window’;

const Row = ({ index, style }) => (
<div style={style}>
{/* Render item based on index */}
</div>
);
function LargeList({ items }) {
return (
<List
height={500}
itemCount={items.length}
itemSize={50}
width={300}
>
{Row}
</List>
);
}

Address these items and you can greatly improve your React app’s performance and ensure a smoother user experience. Remember to continually monitor your app’s performance and make adjustments as needed to keep it running at optimal speed.

Resources

--

--