April 1, 2025

Tối ưu hiệu suất trong React với memo và useMemo
Cách sử dụng memo và useMemo để tránh render không cần thiết
Giới thiệu
Khi phát triển ứng dụng React, hiệu suất là một yếu tố quan trọng. Nếu không kiểm soát tốt quá trình render, ứng dụng có thể trở nên chậm chạp, đặc biệt là với các component phức tạp.
Hai kỹ thuật phổ biến để tối ưu hiệu suất render trong React là React.memo
và useMemo
. Chúng giúp tránh việc render lại không cần thiết, từ đó cải thiện hiệu suất ứng dụng.
1. React.memo
– Ghi nhớ component để tránh render lại
Mặc định, một component con sẽ bị render lại khi component cha render, dù props không thay đổi. Điều này có thể gây lãng phí tài nguyên.
React.memo
giúp React "ghi nhớ" component và chỉ re-render khi props thực sự thay đổi.
Cách sử dụng React.memo
import React from "react";
const Button = React.memo(({ onClick, children }: { onClick: () => void; children: React.ReactNode }) => {
console.log("Button render");
return <button onClick={onClick}>{children}</button>;
});
export default function App() {
const [count, setCount] = React.useState(0);
return (
<div>
<h1>Count: {count}</h1>
<Button onClick={() => setCount(count + 1)}>Tăng</Button>
</div>
);
}
Giải thích:
- Khi
App
re-render, componentButton
cũng sẽ bị re-render theo mặc định, ngay cả khi props không thay đổi. React.memo
giúp ngăn chặn điều này bằng cách ghi nhớ kết quả render trước đó và chỉ re-render nếu props thay đổi.- Trong ví dụ trên, nếu
onClick
không thay đổi giữa các lần render,Button
sẽ không bị render lại. - Điều này giúp giảm số lần render không cần thiết, đặc biệt hữu ích khi component con phức tạp hoặc chứa nhiều logic.
Khi nào nên dùng React.memo
?
- Khi component con có render phức tạp.
- Khi component con nhận props không đổi từ component cha.
- Khi cần tối ưu hiệu suất trong danh sách lớn hoặc UI động.
Không nên dùng React.memo
cho mọi component Nếu component render nhanh, memo
có thể khiến React phải tốn công kiểm tra props, làm giảm hiệu suất.
2. useMemo
– Ghi nhớ giá trị để tránh tính toán lại
useMemo
giúp lưu lại kết quả tính toán và chỉ cập nhật khi dependency thay đổi. Điều này hữu ích khi tính toán phức tạp hoặc xử lý dữ liệu lớn.
Cách sử dụng useMemo
import React, { useState, useMemo } from "react";
function App() {
const [count, setCount] = useState(0);
const [number, setNumber] = useState(10);
const expensiveCalculation = (num: number) => {
console.log("Tính toán...");
return num * 2;
};
// Chỉ tính toán lại khi number thay đổi
const memoizedValue = useMemo(() => expensiveCalculation(number), [number]);
return (
<div>
<h1>Kết quả: {memoizedValue}</h1>
<button onClick={() => setNumber(number + 1)}>Tăng Number</button>
<button onClick={() => setCount(count + 1)}>Tăng Count</button>
<p>Count: {count}</p>
</div>
);
}
export default App;
Giải thích:
useMemo
lưu kết quả củaexpensiveCalculation(number)
, chỉ tính toán lại khinumber
thay đổi.- Nếu chỉ
count
thay đổi, React sử dụng lại giá trị đã tính trước đó, giúp tăng hiệu suất.
Khi nào nên dùng useMemo?
- Khi tính toán phức tạp (ví dụ: lọc danh sách, tính toán toán học).
- Khi dữ liệu không cần thay đổi thường xuyên.
- Khi render lại component có thể gây chậm UI.
Không nên dùng useMemo
với các giá trị tính toán đơn giản, vì React vẫn phải kiểm tra dependency array.
3. memo vs. useMemo – Sử dụng khi nào?
Trường hợp sử dụng | Dùng React.memo | Dùng useMemo |
---|---|---|
Tránh re-render component con | ✅ | ❌ |
Tối ưu giá trị tính toán nặng | ❌ | ✅ |
Component nhận props không đổi | ✅ | ❌ |
Tránh tính toán lại trong mỗi render | ❌ | ✅ |
Kết luận
- Dùng
React.memo
khi muốn tránh re-render component không cần thiết. - Dùng
useMemo
khi muốn tối ưu hiệu suất của các tính toán phức tạp. - Đừng lạm dụng! Chỉ dùng khi thực sự có vấn đề về hiệu suất, tránh làm code phức tạp hơn.
Optimizing Performance in React with memo and useMemo
How to use memo and useMemo to prevent unnecessary renders
Introduction
When developing React applications, performance is a crucial factor. If rendering is not well-managed, the app can become sluggish, especially with complex components.
Two popular techniques for optimizing rendering performance in React are React.memo
and useMemo
. They help avoid unnecessary re-renders, improving the overall performance of your application.
1. React.memo
– Memoizing a component to prevent unnecessary renders
By default, a child component re-renders whenever its parent renders, even if the props haven’t changed. This can waste resources.
React.memo
allows React to "remember" a component and only re-render it when its props actually change.
How to use React.memo
import React from "react";
const Button = React.memo(({ onClick, children }: { onClick: () => void; children: React.ReactNode }) => {
console.log("Button render");
return <button onClick={onClick}>{children}</button>;
});
export default function App() {
const [count, setCount] = React.useState(0);
return (
<div>
<h1>Count: {count}</h1>
<Button onClick={() => setCount(count + 1)}>Increase</Button>
</div>
);
}
Explanation:
- When
App
re-renders, theButton
component will also re-render by default, even if the props haven't changed. React.memo
helps prevent this by caching the previous render result and only re-rendering if the props change.- In the example above, if
onClick
doesn’t change between renders, theButton
won’t re-render. - This helps reduce unnecessary renders, especially useful for complex or logic-heavy child components.
When should you use React.memo
?
- When the child component has expensive rendering logic.
- When the child receives props that don’t change between renders.
- When optimizing performance for large lists or dynamic UIs.
You shouldn't use React.memo
for every component. If a component renders quickly, memoization can add unnecessary overhead due to props comparison, which might actually reduce performance.
2. useMemo
– Memoizing a value to avoid re-computation
useMemo
helps cache computed values and only recomputes them when dependencies change. This is useful for expensive calculations or large data processing.
How to use useMemo
import React, { useState, useMemo } from "react";
function App() {
const [count, setCount] = useState(0);
const [number, setNumber] = useState(10);
const expensiveCalculation = (num: number) => {
console.log("Calculating...");
return num * 2;
};
// Only re-computes when 'number' changes
const memoizedValue = useMemo(() => expensiveCalculation(number), [number]);
return (
<div>
<h1>Result: {memoizedValue}</h1>
<button onClick={() => setNumber(number + 1)}>Increase Number</button>
<button onClick={() => setCount(count + 1)}>Increase Count</button>
<p>Count: {count}</p>
</div>
);
}
export default App;
Explanation:
useMemo
stores the result ofexpensiveCalculation(number)
and only recomputes it whennumber
changes.- If only
count
changes, React uses the previously computed value, helping improve performance.
When should you use useMemo
?
- When performing expensive calculations (e.g., filtering a list, mathematical operations).
- When data doesn’t change frequently.
- When component re-renders could slow down the UI.
You shouldn’t use useMemo
for simple calculations, as React still needs to check the dependency array.
3. memo vs. useMemo – When to use which?
Use Case | Use React.memo | Use useMemo |
---|---|---|
Prevent re-render of child component | ✅ | ❌ |
Optimize heavy computations | ❌ | ✅ |
Component receives unchanged props | ✅ | ❌ |
Avoid re-computing values on render | ❌ | ✅ |
Conclusion
- Use
React.memo
to prevent unnecessary re-renders of components. - Use
useMemo
to optimize performance for expensive computations. - Don’t overuse! Only apply them when facing real performance issues to avoid adding unnecessary complexity to your code.