Tối ưu hiệu năng rendering cho React Web và React Native: Memoization, Virtualization và Lazy Loading

15 lượt xem · 2 trả lời

1. 12:59 12/10/2026
Hiệu năng là yếu tố quyết định trải nghiệm người dùng trên cả web và mobile. Dưới đây là ba kỹ thuật cốt lõi bạn có thể áp dụng ngay hôm nay để giảm thiểu render không cần thiết và tăng tốc độ tải trang. 1. Memoization với React.memo, useMemo và useCallback - React.memo: Bọc component con để chỉ render lại khi props thay đổi thực sự. Ví dụ: const UserCard = React.memo(({name, avatar}) => …). - useMemo: Cache kết quả tính toán nặng (ví dụ: lọc danh sách 10 000 mục) để tránh chạy lại mỗi lần render cha. - useCallback: Giữ tham chiếu hàm ổn định, tránh tạo hàm mới khiến component con bị re‑render. Lưu ý: Chỉ dùng khi profiling cho thấy bottleneck; lạm dụng sẽ tăng bộ nhớ. 2. Virtualization (danh sách ảo) cho dữ liệu lớn - Web: react-window hoặc react-virtualized render chỉ các item nằm trong viewport. Ví dụ: FixedSizeList với height=600, itemCount=5000, itemSize=50. - React Native: FlashList (từ @shopify/flash-list) thay thế FlatList, tự động đo lường và reuse view, giảm GC spikes. Kết quả: Thời gian render danh sách 5 000 mục giảm từ ~1.2 s xuống <200 ms. 3. Lazy Loading và Code Splitting - Web: React.lazy + Suspense cho route hoặc component nặng (biểu đồ, editor). Kết hợp với dynamic import của Webpack/Vite để tách bundle. - React Native: Sử dụng react-native-dynamic-import hoặc Expo Router lazy routes. Chỉ tải bundle khi màn hình được điều hướng tới. Mẹo: Preload các route quan trọng (dashboard, profile) bằng link rel=preload hoặc useEffect gọi import() khi app idle. Checklist nhanh trước khi deploy: - Chạy React DevTools Profiler, tìm component render >16 ms. - Áp dụng React.memo cho các component pure. - Thay FlatList bằng FlashList nếu danh sách >200 item. - Tách bundle theo route, đo lường First Contentful Paint (FCP) và Time to Interactive (TTI). Áp dụng ba kỹ thuật trên theo thứ tự ưu tiên: memoization → virtualization → lazy loading. Bạn sẽ thấy cải thiện rõ rệt về độ mượt và thời gian tải mà không cần thay đổi kiến trúc tổng thể.
0 Facebook
2. 14:02 13/10/2026
Trả lời Quản Trị Viên Hiệu năng là yếu tố quyết định trải nghiệm người dùng trên cả web và mobile. Dưới đây là ba kỹ thuật cốt lõi bạn có thể …
Cảm ơn bài viết tổng hợp rất thực tế. Mình vừa migrate một project RN từ FlatList sang FlashList cho danh sách chat 3000+ item, giảm re-render rõ rệt nhưng gặp vấn đề `estimatedItemSize` không chính xác khiến layout shift lúc scroll nhanh. Khuyến nghị của Shopify là dùng `getItemLayout` nếu item cố định height, nhưng với chat bubble height động thì phải tính toán thủ công khá mệt. Về memoization, mình hay thấy team junior bọc `React.memo` cho mọi component con dù props chỉ là primitive, dẫn đến overhead so sánh props lớn hơn gain. Rule of thumb của mình: chỉ memo khi component render >16ms hoặc có pure computation bên trong. Lazy loading route-based thì ok, nhưng component-level lazy (React.lazy + Suspense) đôi khi gây flash layout nếu fallback không reserve space. Các bạn có kinh nghiệm handle CLS khi lazy load component nặng không?
0
3. 15:18 13/10/2026
Trả lời Nguyễn Thảo Cảm ơn bài viết tổng hợp rất thực tế. Mình vừa migrate một project RN từ FlatList sang FlashList cho danh sách chat 3000…
Mình cũng gặp cái lỗi `estimatedItemSize` trên FlashList lúc đầu, cuối cùng phải viết hook custom tính toán height dựa trên nội dung tin nhắn (độ dài text, có media không...) rồi cache lại vào `getItemLayout`. Việc tính toán thủ công ban đầu tốn chút effort nhưng scroll sau đó mượt hẳn, không bị nhảy layout nữa. Về `React.memo`, mình đồng ý hoàn toàn. Over-memoization là bẫy thường gặp, đặc biệt khi props là object/array mới tạo mỗi render (inline function, style object) thì so sánh shallow bằng `Object.is` lại trả về false, gây re-render vô ích kèm overhead so sánh. Rule 16ms là tham chiếu tốt, thực tế mình thường profile bằng DevTools Profiler (Record why each component rendered) mới quyết định memo. Câu hỏi về CLS khi `React.lazy`: mình hay dùng trick set `min-height` hoặc `aspect-ratio` cho wrapper container của `Suspense` fallback (skeleton/spinner) khớp với kích thước component thật sau khi load xong. Nếu component nặng load data async bên trong, có thể kết hợp `useTransition` để giữ UI cũ mượt mà hơn. Các bạn có thử dùng `useDeferredValue` cho phần nội dung list trong khi chờ lazy component hydrate chưa?
0
Vui lòng đăng nhập để tham gia trả lời chủ đề này.
Điều hướng nhanh

Bạn muốn khám phá điều gì?

Tìm chủ đề, bài viết hoặc đi thẳng đến một khu vực của cộng đồng.

Esc để đóng Ctrl K để mở lại