
Tối ưu hiệu suất React: Từ cơ bản đến nâng cao
Hướng dẫn chi tiết về các kỹ thuật tối ưu hiệu suất trong React applications.
Tối ưu hiệu suất React: Từ cơ bản đến nâng cao
Hiệu suất là yếu tố quan trọng trong việc phát triển ứng dụng React. Hãy cùng tìm hiểu các kỹ thuật tối ưu từ cơ bản đến nâng cao.
React.memo và useMemo
React.memo cho Components
const ExpensiveComponent = React.memo(({ data, onUpdate }) => {
const expensiveValue = useMemo(() => {
return data.reduce((acc, item) => acc + item.value, 0);
}, [data]);
return (
<div>
<h3>Total: {expensiveValue}</h3>
<button onClick={onUpdate}>Update</button>
</div>
);
});
useMemo cho expensive calculations
function ProductList({ products, searchTerm, sortBy }) {
const filteredAndSortedProducts = useMemo(() => {
const filtered = products.filter(product =>
product.name.toLowerCase().includes(searchTerm.toLowerCase())
);
return filtered.sort((a, b) => {
if (sortBy === 'price') return a.price - b.price;
if (sortBy === 'name') return a.name.localeCompare(b.name);
return 0;
});
}, [products, searchTerm, sortBy]);
return (
<div>
{filteredAndSortedProducts.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}
useCallback cho Event Handlers
function TodoList({ todos, onToggle, onDelete }) {
const handleToggle = useCallback((id) => {
onToggle(id);
}, [onToggle]);
const handleDelete = useCallback((id) => {
onDelete(id);
}, [onDelete]);
return (
<div>
{todos.map(todo => (
<TodoItem
key={todo.id}
todo={todo}
onToggle={handleToggle}
onDelete={handleDelete}
/>
))}
</div>
);
}
Code Splitting với React.lazy
Component-level splitting
const LazyDashboard = React.lazy(() => import('./Dashboard'));
const LazyProfile = React.lazy(() => import('./Profile'));
const LazySettings = React.lazy(() => import('./Settings'));
function App() {
return (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/dashboard" element={<LazyDashboard />} />
<Route path="/profile" element={<LazyProfile />} />
<Route path="/settings" element={<LazySettings />} />
</Routes>
</Suspense>
</Router>
);
}
Dynamic imports với conditions
function AdminPanel() {
const [showAdvanced, setShowAdvanced] = useState(false);
const [AdvancedComponent, setAdvancedComponent] = useState(null);
useEffect(() => {
if (showAdvanced && !AdvancedComponent) {
import('./AdvancedSettings').then(module => {
setAdvancedComponent(() => module.default);
});
}
}, [showAdvanced, AdvancedComponent]);
return (
<div>
<button onClick={() => setShowAdvanced(!showAdvanced)}>
Toggle Advanced Settings
</button>
{showAdvanced && AdvancedComponent && <AdvancedComponent />}
</div>
);
}
Virtual Scrolling
Cho danh sách lớn, sử dụng virtual scrolling:
import { FixedSizeList as List } from 'react-window';
function VirtualizedList({ items }) {
const Row = ({ index, style }) => (
<div style={style}>
<div className="item">
{items[index].name}
</div>
</div>
);
return (
<List
height={600}
itemCount={items.length}
itemSize={50}
width="100%"
>
{Row}
</List>
);
}
Image Optimization
Lazy loading images
function LazyImage({ src, alt, className }) {
const [isLoaded, setIsLoaded] = useState(false);
const [isInView, setIsInView] = useState(false);
const imgRef = useRef();
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsInView(true);
observer.disconnect();
}
},
{ threshold: 0.1 }
);
if (imgRef.current) {
observer.observe(imgRef.current);
}
return () => observer.disconnect();
}, []);
return (
<div ref={imgRef} className={className}>
{isInView && (
<img
src={src}
alt={alt}
onLoad={() => setIsLoaded(true)}
style={{
opacity: isLoaded ? 1 : 0,
transition: 'opacity 0.3s'
}}
/>
)}
</div>
);
}
State Management Optimization
Tách state để tránh unnecessary re-renders
// ❌ Tránh - một state object lớn
function App() {
const [state, setState] = useState({
user: null,
posts: [],
comments: [],
ui: { loading: false, error: null }
});
// Mỗi khi update bất kỳ field nào, toàn bộ component re-render
}
// ✅ Tốt hơn - tách state
function App() {
const [user, setUser] = useState(null);
const [posts, setPosts] = useState([]);
const [comments, setComments] = useState([]);
const [ui, setUi] = useState({ loading: false, error: null });
// Chỉ re-render khi state liên quan thay đổi
}
Bundle Analysis
Sử dụng webpack-bundle-analyzer để phân tích bundle:
npm install --save-dev webpack-bundle-analyzer
{
"scripts": {
"analyze": "npm run build && npx webpack-bundle-analyzer build/static/js/*.js"
}
}
Performance Monitoring
Sử dụng React DevTools Profiler
import { Profiler } from 'react';
function onRenderCallback(id, phase, actualDuration) {
console.log('Component:', id);
console.log('Phase:', phase);
console.log('Duration:', actualDuration);
}
function App() {
return (
<Profiler id="App" onRender={onRenderCallback}>
<Header />
<Main />
<Footer />
</Profiler>
);
}
Kết luận
Tối ưu hiệu suất React đòi hỏi sự hiểu biết sâu về cách React hoạt động và áp dụng đúng kỹ thuật cho từng tình huống. Những kỹ thuật này sẽ giúp ứng dụng React của bạn chạy mượt mà và mang lại trải nghiệm tốt cho người dùng.
Nhớ rằng: Đo lường trước khi tối ưu. Sử dụng React DevTools và browser performance tools để xác định bottlenecks thực sự.
Tags: React, Performance, Optimization, JavaScript, Web Development

