← Về danh sách bài họcBài 15/25
🆔 Bài 15: useId & useSyncExternalStore
🎯 Sau bài học này, bạn sẽ:
- Dùng useId tạo unique IDs an toàn cho SSR
- Hiểu useSyncExternalStore cho external state
- Kết nối React với non-React state (browser APIs, stores)
1. useId - Unique IDs An Toàn
import { useId } from 'react';
function FormField({ label, type = 'text' }) {
const id = useId(); // Tạo unique ID, safe cho SSR
return (
<div>
<label htmlFor={id}>{label}</label>
<input id={id} type={type} />
<p id={`${id}-hint`}>Hint text</p>
</div>
);
}
// Sử dụng: mỗi instance có ID khác nhau
<FormField label="Email" /> {/* id=":r1:" */}
<FormField label="Password" /> {/* id=":r2:" */}⚠️ Không dùng useId cho: key prop trong lists, CSS selectors. useId dành cho liên kết HTML attributes (htmlFor, aria-describedby).
2. useSyncExternalStore
Đồng bộ React với state từ bên ngoài (browser APIs, third-party stores):
import { useSyncExternalStore } from 'react';
// Custom hook: theo dõi online status
function useOnlineStatus() {
return useSyncExternalStore(
// subscribe: đăng ký listener
(callback) => {
window.addEventListener('online', callback);
window.addEventListener('offline', callback);
return () => {
window.removeEventListener('online', callback);
window.removeEventListener('offline', callback);
};
},
// getSnapshot: lấy giá trị hiện tại
() => navigator.onLine,
// getServerSnapshot (SSR)
() => true
);
}
function StatusBar() {
const isOnline = useOnlineStatus();
return <p>{isOnline ? '🟢 Online' : '🔴 Offline'}</p>;
}
// Window size hook
function useWindowWidth() {
return useSyncExternalStore(
(cb) => { window.addEventListener('resize', cb); return () => window.removeEventListener('resize', cb); },
() => window.innerWidth,
() => 1024
);
}📝 Tóm Tắt
useId: tạo unique IDs, SSR-safe, cho HTML attributesuseSyncExternalStore: đồng bộ React với external state- useSyncExternalStore cho: browser APIs, WebSocket, third-party stores