- Published on
How to Speed Up React Apps

- Authors
- Name
- Nguyen Pham
Overview
React is the most popular JavaScript library today, developed and maintained by Facebook. It helps us build web applications easily and quickly. However, optimizing React applications to increase page loading speed is a problem that many developers face.
In this article, we will not talk about configuring optimization tools such as Webpack, Vite... but will focus on optimizing React source code to increase page loading speed.
Using useCallback
Let's look at the following code snippet:
export default function Demo() {
const toggleTheme = () => {
if (theme === "dark") {
setTheme("light");
}
};
return (
<button onClick={() => toggleTheme()}>Toggle Theme</button>
);
}
Improve it with useCallback
:
import { useCallback } from "react";
export default function Demo() {
const toggleTheme = useCallback(() => {
if (theme === "dark") {
setTheme("light");
}
}, [theme, setTheme]);
return (
<button onClick={toggleTheme}>Toggle Theme</button>
);
}
With this way, React will not have to create a new function every time the component is re-rendered, helping to reduce memory usage and increase page loading speed.
Using useMemo
Similar to useCallback
, useMemo
helps us optimize React source code by storing previously calculated values.
export default function Demo() {
return (
<BlockBG
bgImage="/imgs/madelab/homepagebg.jpg"
/>
);
}
Improve it with useMemo
:
import { useMemo } from "react";
export default function Demo() {
const blockBGProps = useMemo(() => ({
bgImage: "/imgs/madelab/homepagebg.jpg",
}), []);
return (
<BlockBG {...blockBGProps} />
);
}
Thus, React will not have to create a new object every time the component is re-rendered, everything will be stored in memory.
Change the way to import
Instead of importing all components from the React library:
import BlockNewletters from "./BlockNewletters";
export default function Demo() {
return (
<>
...
<BlockNewletters />
...
</>
)
}
Let's import each component directly:
import React, { useEffect, useState, useCallback } from "react";
import BlockNewletters from "./BlockNewletters";
const MemoizedBlockNewletters = React.memo(BlockNewletters);
export default function Demo() {
return (
<>
...
<MemoizedBlockNewletters />
...
</>
)
}
With this way, React will not have to load the entire React library every time it renders a component. Instead, it only loads the necessary components first.
Using React.memo
React.memo
helps us optimize React source code by storing the previously rendered result.
import { Modal } from "antd";
export default function Demo() {
return (
<Modal
open={isModalOpen === "autosubscribe"}
>
</Modal>
)
}
Improve it with:
import React, { useCallback } from "react";
import { Modal } from "antd";
const MemoizedModal = React.memo(Modal);
export default function Demo() {
return (
<MemoizedModal
open={isModalOpen === "autosubscribe"}
>
</MemoizedModal>
)
}
If-Else syntax
Instead of using the if-else syntax:
{loading && (
<Loading />
)}
{!loading && (
<Content />
)}
Use a shorter syntax:
{loading ? <Loading /> : <Content />}
Using lazy and Suspense
React provides lazy
and Suspense
to load components when needed.
import BlockEditor from "@/app/components/block-editor";
export default function Demo() {
return (
<BlockEditor />
)
}
Improve it with:
import React, { lazy, Suspense } from "react";
export default function Demo() {
const LazyBlockEditor = memo(lazy(() => import("@/app/components/block-editor")));
return (
<Suspense fallback={<>Loading...</>}>
<LazyBlockEditor />
</Suspense>
)
}
Working with loops
Instead of using a regular loop:
export default function Demo() {
return (
<>
{items.map((item, index) => (
<Item key={index} item={item} />
))}
</>
)
}
Use the following method:
import { useMemo } from "react";
export default function Demo() {
const socialIcons = useMemo(() => {
return items.map((item, index) => (
<Item key={index} item={item} />
));
}, [items]);
return (
<>
{socialIcons}
</>
)
}
With this way, React will not have to recalculate every time the component is re-rendered.
Working with Font render
Instead of using fonts from FontAwesome:
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
export default function Demo() {
return (
<FontAwesomeIcon icon={faCoffee} className="icon" style={{ color: "red" }} />
)
}
Use the following method:
import { useMemo } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
const MemoizedFontAwesomeIcon = React.memo(FontAwesomeIcon);
const iconProps = useMemo(() => ({
className: "icon",
style: { color: "red" }
}), []);
export default function Demo() {
return (
<MemoizedFontAwesomeIcon {...iconProps} icon={faCoffee} />
)
}
Caching API requests
Instead of calling the API every time the component is re-rendered:
import { useEffect, useState } from "react";
export default function Demo() {
const [data, setData] = useState([]);
useEffect(() => {
fetch("https://api.blog.nguyenpham.pro/posts")
.then(res => res.json())
.then(data => setData(data));
}, []);
return (
<>
{data.map((item, index) => (
<Item key={index} item={item} />
))}
</>
)
}
Use the following method:
import { useCallback, useEffect, useState, useMemo } from "react";
export default function Demo() {
const [data, setData] = useState([]);
const fetchData = useCallback(() => {
fetch("https://api.blog.nguyenpham.pro/posts", { cache: "force-cache" })
.then(res => res.json())
.then(data => setData(data));
}, []);
const memoizedData = useMemo(() => data, [data]);
useEffect(() => {
fetchData();
}, [fetchData]);
return (
<>
{memoizedData.map((item, index) => (
<Item key={index} item={item} />
))}
</>
)
}
Conclusion
The above are some ways to optimize React source code to increase page loading speed. I hope this article will help you optimize your React application. If you have any questions or comments, please leave a message. Wish you success!

Nguyen Pham
Làm việc tại phòng thí nghiệm MADE, Texas, USA. Là một người đam mê với công nghệ và thích chia sẻ kiến thức với mọi người.