Sửa lỗi 'TypeError: Cannot destructure property 'user' of 'useContext(...)' as it is undefined'

beginner⚛️ React2026-03-30| React 16.8+, Next.js (Pages và App Router), Vite, Create React App.

Error Message

TypeError: Cannot destructure property 'user' of 'useContext(...)' as it is undefined.
#react#useContext#nextjs#lỗi-javascript#phát-triển-web

Cách Khắc Phục Nhanh

Lỗi này xảy ra do component gọi useContext nằm ngoài cây <MyContext.Provider>. React sẽ tìm kiếm ngược lên trên để tìm một Provider, và nếu không thấy, nó sẽ trả về giá trị mặc định—thường là undefined. Để khắc phục, hãy di chuyển lệnh gọi useContext vào trong một component con hoặc bao bọc điểm khởi đầu của ứng dụng (như main.jsx hoặc _app.js) bằng Provider.

// ❌ SAI: Component nằm cùng cấp với provider
function App() {
  return (
    <>
      <UserProvider>
         <Header />
      </UserProvider>
      <UserProfile /> // Lỗi! UserProfile nằm ngoài cây
    </>
  );
}

// ✅ ĐÚNG: Component được lồng bên trong provider
function App() {
  return (
    <UserProvider>
       <Header />
       <UserProfile /> // Hoạt động hoàn hảo
    </UserProvider>
  );
}

Tại Sao Lỗi Này Xảy Ra

Khi bạn chạy const UserContext = createContext(); mà không truyền vào đối số, React sẽ đặt giá trị mặc định là undefined. Sau đó, khi bạn cố gắng destructure { user } từ một context chưa được "provided" (cung cấp), về cơ bản bạn đang cố chạy { user } = undefined. JavaScript sẽ ngay lập tức ném ra một lỗi TypeError vì bạn không thể lấy thuộc tính từ một giá trị rỗng.

Hãy coi Context giống như tín hiệu radio. Nếu component của bạn không nằm trong phạm vi phát sóng (Provider), nó sẽ chỉ nghe thấy tiếng rè.

Các Sai Lầm Thường Gặp và Giải Pháp

1. Sử Dụng Context Trong Cùng Một Component Định Nghĩa Provider

Các lập trình viên React thường cố gắng sử dụng useContext ngay trong tệp mà họ render Provider. Điều này sẽ luôn thất bại. Một Provider chỉ "phát sóng" tới các descendants (component con cháu) của nó, chứ không phải chính nó.

// Component này sẽ không tìm thấy context của chính nó
export default function Dashboard() {
  const { user } = useContext(UserContext); // Kết quả: undefined

  return (
    <UserContext.Provider value={{ user: 'Jane Doe' }}>
      <Sidebar />
    </UserContext.Provider>
  );
}

Cách khắc phục: Bao bọc component App cấp cao nhất hoặc tạo một wrapper ContextProvider riêng biệt để đảm bảo dữ liệu có sẵn trên toàn cầu.

2. Mô Hình "Safe Hook"

Thay vì import useContext và đối tượng context vào mọi tệp, tôi khuyên bạn nên tạo một custom hook. Điều này giúp tiết kiệm thời gian và cung cấp thông báo lỗi hữu ích hơn nhiều so với lỗi crash mặc định của JavaScript.

// UserContext.js
import { createContext, useContext, useState } from 'react';

const UserContext = createContext(null);

export function UserProvider({ children }) {
  const [user, setUser] = useState({ id: 1, name: 'Guest' });
  return (
    <UserContext.Provider value={{ user, setUser }}>
      {children}
    </UserContext.Provider>
  );
}

export function useUser() {
  const context = useContext(UserContext);
  if (!context) {
    throw new Error('useUser must be used within a UserProvider. Check your component tree!');
  }
  return context;
}

Bằng cách ném ra một lỗi tùy chỉnh, bạn sẽ biết chính xác provider nào đang thiếu chỉ trong khoảng 2 giây thay vì phải tìm kiếm trong stack traces.

3. Những Lưu Ý Với Next.js App Router

Trong Next.js, các tệp layout.js là nơi tuyệt vời để đặt Provider, nhưng chúng phải là Client Components. Hãy thêm chỉ thị "use client" ở đầu tệp provider của bạn. Ngoài ra, hãy nhớ rằng một layout.js không thể sử dụng context mà chính nó định nghĩa; chỉ page.js và các con khác bên trong {children} mới có thể truy cập được.

4. Vấn Đề Phụ Thuộc Vòng (Circular Dependency)

Nếu AuthContext.js import Login.js, và Login.js lại import AuthContext.js, đối tượng context của bạn có thể bị undefined trong lần render đầu tiên. Đây là một lỗi thầm lặng trong các ứng dụng lớn. Hãy luôn giữ lệnh gọi createContext trong một tệp nhỏ, biệt lập và không import bất cứ thứ gì từ thư mục component của bạn.

Cách Kiểm Tra Việc Khắc Phục

  • Kiểm tra bằng React DevTools: Mở DevTools của trình duyệt và đi đến tab "Components". Nhấp vào component của bạn. Nếu bạn không thấy Context.Provider phía trên nó trong cấu trúc phân cấp, đó chính là vấn đề.
  • Console Log Context thô: Trước khi destructuring, hãy thêm console.log('Context Value:', useContext(MyContext)). Nếu nó in ra null hoặc undefined, vị trí đặt Provider của bạn đã sai.
  • Kiểm tra tên Import: Đảm bảo bạn không vô tình import Provider trong khi thực chất muốn import chính đối tượng Context.

Lời Kết

Hầu hết các lỗi useContext đều liên quan đến cấu trúc. Nếu bạn gặp lỗi này, 99% trường hợp bạn chỉ cần di chuyển Provider lên vị trí cao hơn trong cây component. Đối với bất kỳ ứng dụng thực tế nào, hãy sử dụng mô hình Safe Hook để phát hiện các vấn đề này trong quá trình phát triển trước khi chúng tiếp cận người dùng.

Related Error Notes