10 Tips to Optimize and Improve Performance in React 18
By Amaresh Adak
Introduction
React 18 is the latest version of the popular React JavaScript library. It introduces a number of new features and improvements, including a new rendering engine, Suspense, and concurrent rendering. These features can help to improve the performance of React applications. In this blog post, we will discuss 10 tips to optimize and improve performance in React 18. These tips will help you to create React applications that are fast, responsive, and user-friendly.
If you want to learn about advanced JavaScript tips and new features, then read my advanced JavaScript blog post. Click here to learn about the advanced JavaScript blog.
In this guide, we’ll take a look at:
Table Of Contents
- Use Concurrent Rendering
- Use the useMemo Hook
- Use the useCallback Hook
- Use the useReducer Hook
- Use the useRef Hook
- Use CSS Modules in React 18
- Use Image Optimization Techniques
- Use a CDN for Static Assets
- Use Performance Profilers in React 18
- Conclusion
1. Use Suspense in React 18
Suspense is a new feature in React 18 that allows you to lazy-load components. This can help to improve the performance of your application by preventing the loading of components that are not visible on the screen.
To use Suspense, you need to wrap the component that you want to lazy-load in a Suspense component. You can then use the SuspenseList component to render a list of lazy-loaded components.
For example, the following code shows how to lazy-load a list of users:
const Users = () => {
const [users, setUsers] = useState([]);
return (
<Suspense fallback={Loading...}>
<SuspenseList>
{users.map((user) => (
<User key={user.id} user={user} />
))}
</SuspenseList>
</Suspense>
);
};
2. Use Concurrent Rendering
Concurrent rendering is another new feature in React 18 that allows you to render multiple components at the same time. This can help to improve the performance of your application by reducing the amount of time that the browser has to wait for components to render.
To use concurrent rendering, you need to wrap the components that you want to render concurrently in a Concurrent component. You can then use the useIsConcurrent hook to check if a component is being rendered concurrently.
For example, the following code shows how to render two components concurrently:
const App = () => {
const [isConcurrent, setIsConcurrent] = useState(false);
return (
<button onClick={() => setIsConcurrent(true)}>
Toggle Concurrent Rendering
</button>
{isConcurrent ? (
<Concurrent>
<ComponentA />
<ComponentB />
</Concurrent>
) : (
<>
<ComponentA />
<ComponentB />
</>
)}
);
};
const ComponentA = () => Component A;
const ComponentB = () => Component B;
3. Use the useMemo Hook
The useMemo hook is a React hook that allows you to memoize the result of a function. This can help to improve the performance of your application by preventing the function from being called unnecessarily.
To use the useMemo hook, you need to pass the function that you want to memoize and a list of dependencies to the hook. The hook will then return the memoized value of the function, which will be updated only when the dependencies change.
For example, the following code shows how to use the useMemo hook to memoize a function that calculates the total number of users:
const Users = () => {
const [users, setUsers] = useState([]);
const totalUsers = useMemo(() => {
return users.length;
}, [users]);
return (
<h1>Total Users: {totalUsers}</h1>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
};
4. Use the useCallback Hook
The useCallback hook is a React hook that allows you to memoize the result of a callback function. This can help to improve the performance of your application by preventing the callback function from being called unnecessarily.
To use the useCallback hook, you need to pass the callback function and a list of dependencies to the hook
5. Use the useReducer Hook
The useReducer hook is a React hook that allows you to manage state in a more performant way than using the useState hook. This is because the useReducer hook only updates the state when the value of the reducer function changes.
To use the useReducer hook, you need to pass the reducer function and an initial state to the hook. The hook will then return a state variable and a dispatch function. The state variable will be updated when the dispatch function is called.
For example, the following code shows how to use the useReducer hook to manage the state of a counter:
const [counter, dispatch] = useReducer((state, action) => {
switch (action) {
case "increment":
return state + 1;
case "decrement":
return state - 1;
default:
return state;
}
}, 0);
const increment = () => dispatch("increment");
const decrement = () => dispatch("decrement");
return (
<h1>Counter: {counter}</h1>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>{" "}
);
6. Use the useRef Hook
The useRef hook is a React hook that allows you to create a ref object. A ref object is a mutable value that can be used to store data that needs to be accessible outside of the current function scope.
To use the useRef hook, you need to pass a default value to the hook. The hook will then return a ref object that contains the default value.
For example, the following code shows how to use the useRef hook to create a ref object that stores the current value of a counter:
const counterRef = useRef(0);
const increment = () => {
counterRef.current += 1;
};
const decrement = () => {
counterRef.current -= 1;
};
return (
<h1>Counter: {counterRef.current}</h1>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>{" "}
);
7. Use CSS Modules in React 18
CSS Modules are a way to create custom CSS styles that are scoped to a specific component. This can help to improve the performance of your application by preventing CSS from being loaded for components that are not visible on the screen.
To use CSS Modules, you need to create a CSS file with the .module.css extension. You can then use the @import keyword to import the CSS file into your React component.
For example, the following code shows how to use CSS Modules to create a custom style for a component:
const MyComponent = () => {
return <h1>This is my component</h1>
}
const styles = `
.my-component {
color: red;
} `
export default MyComponent
// Import the CSS file into the component
import styles from "./styles.module.css"
8. Use Image Optimization Techniques
Images can be a major performance bottleneck in React applications. There are a number of techniques that you can use to optimize images and improve the performance of your application.
One technique is to use lazy loading. Lazy loading is a technique that delays the loading of images until they are visible on the screen. This can help to improve the performance of your application by preventing images from being loaded for components that are not visible.
import React, { useState } from "react";
import { Image, lazy } from "react-lazyload";
const ImageLazy = ({ src }) => {
const [isLoaded, setIsLoaded] = useState(false);
return (
<Image
src={src}
alt="Image"
key={src}
onLoad={() => setIsLoaded(true)}
onError={() => setIsLoaded(false)}
/>
);
};
const App = () => {
const [images, setImages] = useState([
{
src: "https://placekitten.com/300/300",
},
{
src: "https://placekitten.com/600/600",
},
{
src: "https://placekitten.com/900/900",
},
]);
return (
{images.map((image) => (
<lazy key={image.src}>
<ImageLazy src={image.src} />
</lazy>
))}
);
};
export default App;
Another technique is to use image compression. Image compression is a technique that reduces the size of images without sacrificing quality. This can help to improve the performance of your application by reducing the amount of data that needs to be downloaded.
9. Use a CDN for Static Assets
A CDN (Content Delivery Network) is a network of servers that are distributed around the world. When you use a CDN for static assets, such as images and CSS files, your application will be served from the server that is closest to the user. This can help to improve the performance of your application by reducing the amount.
import React, { useState } from "react";
const App = () => {
const [images, setImages] = useState([
{
src: "https://placekitten.com/300/300",
},
{
src: "https://placekitten.com/600/600",
},
{
src: "https://placekitten.com/900/900",
},
]);
return (
{images.map((image) => (
<img src={image.src} />
))}
);
};
export default App;
10. Use Performance Profilers in React 18
Performance profiler tools can help you to identify performance bottlenecks in your React applications. There are a number of performance profiler tools available, such as the Chrome DevTools and the React Profiler.
To use a performance profiler tool, you need to open the tool and then start recording your application. Once you have started recording, you can interact with your application as you normally would. The performance profiler tool will then show you a breakdown of the performance of your application.
By using a performance profiler tool, you can identify performance bottlenecks in your React applications and then take steps to improve the performance of your application.
Conclusion
By following these tips, you can optimize and improve the performance of your React applications. These tips will help you to create React applications that are fast, responsive, and user-friendly.
Here are some additional tips that you can follow to improve the performance of your React applications:
- Choose a lightweight framework: React is already a lightweight framework, but consider even lighter options for better performance.
- Implement caching: Store data in memory to avoid server loading for improved speed.
- Utilize a content delivery network (CDN): Use a CDN for static assets like images and CSS files, allowing faster delivery from servers closest to users.
- Optimize images: Use lazy loading to delay image loading until they’re visible on the screen. Compress images to reduce download size.
- Optimize CSS: Use CSS modules to scope custom styles to specific components. Minify CSS files by removing unnecessary whitespace and comments.
- Optimize JavaScript: Minify JavaScript files to reduce their size. Utilize code splitting to break down JavaScript code into multiple files for parallel loading and execution.
By implementing these strategies, you can significantly enhance the performance of your React application.