React Compiler: Tự động memo hoá — có thực sự tốt?
Phân tích React Compiler (React Forget) — cách nó tự động memo hoá components và hooks, ưu nhược điểm, và khi nào nên bật trong dự án.
React Compiler (trước đây gọi là React Forget) đã chính thức release stable cùng React 19. Lời hứa: tự động memo hoá mọi thứ, không cần useMemo, useCallback, React.memo thủ công nữa. Nghe tuyệt vời — nhưng thực tế thế nào?
React Compiler làm gì?
Compiler phân tích code tại build time và tự động thêm memoization. Nó hiểu:
- Giá trị nào cần memo (objects, arrays, functions tạo trong render)
- Dependencies của mỗi giá trị
- Component nào cần skip re-render
Trước compiler, bạn viết:
import { useMemo, useCallback, memo } from "react";
const MemoizedChild = memo(function Child({ items, onSelect }) {
return (
<ul>
{items.map((item) => (
<li key={item.id} onClick={() => onSelect(item.id)}>
{item.name}
</li>
))}
</ul>
);
});
function Parent({ data }) {
const [selected, setSelected] = useState(null);
const sortedItems = useMemo(
() => data.sort((a, b) => a.name.localeCompare(b.name)),
[data]
);
const handleSelect = useCallback(
(id: string) => setSelected(id),
[]
);
return <MemoizedChild items={sortedItems} onSelect={handleSelect} />;
}
Sau compiler, bạn chỉ cần viết:
function Child({ items, onSelect }) {
return (
<ul>
{items.map((item) => (
<li key={item.id} onClick={() => onSelect(item.id)}>
{item.name}
</li>
))}
</ul>
);
}
function Parent({ data }) {
const [selected, setSelected] = useState(null);
const sortedItems = data.sort((a, b) => a.name.localeCompare(b.name));
const handleSelect = (id: string) => setSelected(id);
return <Child items={sortedItems} onSelect={handleSelect} />;
}
Code sạch hơn đáng kể. Compiler tự thêm memo ở build output.
Ưu điểm thực tế
1. Ít boilerplate — Không cần useMemo, useCallback, React.memo. Code dễ đọc hơn nhiều.
2. Ít bugs — Dependency arrays là nguồn bug phổ biến. Compiler phân tích đúng dependencies 100%.
3. Performance by default — Junior devs không cần hiểu khi nào cần memo. Compiler handle hết.
4. Gradual adoption — Có thể bật per-file hoặc per-component với directive.
Nhược điểm và gotchas
1. Mutation patterns bị break — Compiler giả sử code follow Rules of React. Nếu bạn mutate objects/arrays trực tiếp, compiler sẽ cache giá trị sai:
Luôn tạo object mới thay vì mutate. Đây là best practice sẵn rồi, nhưng compiler enforce nghiêm hơn.
2. Build time tăng — Compiler cần phân tích toàn bộ component tree. Với project lớn, build có thể chậm hơn 10-20%.
3. Debug khó hơn — Output code có nhiều generated memo calls. Debugging compiled output không dễ.
4. Không phải silver bullet — Compiler memo hoá rendering, nhưng không fix algorithmic issues. O(n²) loop vẫn là O(n²) dù có memo.
Có nên bật ngay?
Bật nếu: Codebase follow Rules of React, không mutate state trực tiếp, team hiểu immutable patterns.
Chờ nếu: Codebase cũ với nhiều mutation patterns, heavily relying on refs for state, hoặc dùng libraries chưa compatible.
Setup trong Next.js
Next.js 15+ hỗ trợ built-in. Chỉ cần thêm vào next.config.ts:
Chạy npx react-compiler-healthcheck trước để kiểm tra codebase compatibility.
Kết luận
React Compiler là bước tiến lớn cho DX và performance. Với codebase mới, bật ngay — không có lý do gì để viết useMemo/useCallback thủ công nữa. Với codebase cũ, chạy healthcheck trước và migrate dần. Tương lai của React là compiler-driven optimization.
Admin
Bình luận (0)
Đăng nhập để bình luận
Chưa có bình luận nào. Hãy là người đầu tiên!