useContext là hook giúp component đọc giá trị từ React Context mà không cần truyền props qua từng cấp. Bạn truyền vào object tạo bởi createContext, hook trả về value của Provider gần nhất phía trên trong cây.
Hãy hình dung Context như bảng thông báo ở đầu hành lang: thay vì chuyền tay tờ giấy qua từng phòng (props drilling), bạn dán thông tin lên bảng và mọi phòng bên dưới đều nhìn lên để đọc. useContext là thao tác nhìn lên bảng đó.
Về cơ chế, React lưu value trên fiber của Provider. Mỗi lần Provider render, React so sánh value mới với giá trị trước bằng Object.is. Nếu khác, React đánh dấu mọi component đã gọi useContext(Context) bên dưới cần re-render, dù chúng chỉ dùng một phần của value. Context không có selector hay so sánh sâu, nên tối ưu identity của value là trách nhiệm của bạn. Nếu value là object hay array, hãy giữ tham chiếu ổn định bằng useMemo khi nội dung không đổi. useContext phải tuân thủ Rules of Hooks và chỉ gọi ở top-level của function component hoặc custom hook.
// Tạo context với giá trị mặc định
const ThemeContext = createContext<'light' | 'dark'>('light');
function App() {
const [theme] = useState<'light' | 'dark'>('dark');
return (
<ThemeContext.Provider value={theme}>
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() {
const theme = useContext(ThemeContext); // đọc giá trị từ Provider gần nhất
return <div className={theme}>Current theme: {theme}</div>;
}- Truyền
value={{ theme, setTheme }}tạo object mới mỗi render khiến mọi consumer re-render dùthemekhông đổi. Khắc phục bằnguseMemocho value hoặc tách thành nhiều Context nhỏ. - Gọi
useContexttrong nhánh điều kiện hoặc saureturnsớm vi phạm Rules of Hooks. defaultValuetrongcreateContextchỉ dùng khi không có Provider phía trên, không phải khi Provider truyềnvalue={undefined}.- Dùng Context cho state thay đổi liên tục như giá trị input hay animation dễ gây re-render diện rộng.
Lưu ý: Dùng Context cho dữ liệu ít thay đổi và cần chia sẻ rộng như theme, locale, auth. Với state cập nhật thường xuyên hoặc cần selector, hãy tách Context, kết hợp memo/useMemo, hoặc chọn thư viện state có selector để hạn chế re-render.