Sửa lỗi React validateDOMNesting: Ngưng đặt <div> bên trong <p>

beginner⚛️ React2026-04-24| React 16.8+, Next.js (Client-side rendering), Chrome DevTools

Error Message

Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>. See ... > p > div.
#react#dom#html#nesting#validateDOMNesting#semantic-html

Cảnh báo trong Console của bạnMọi thứ trông có vẻ hoàn hảo trên màn hình cho đến khi bạn mở Chrome DevTools và bắt gặp một loạt cảnh báo màu vàng. Một trong những lỗi phổ biến nhất là validateDOMNesting. Nó thường xuất hiện bất ngờ với thông báo như thế này:

Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>. 
See App > Layout > p > div.

Ứng dụng của bạn sẽ không bị sập, nhưng bạn đang vi phạm các quy tắc HTML cốt lõi. Về cơ bản, React đang cảnh báo một xung đột: các trình duyệt không cho phép các phần tử cấp khối (block-level) nằm bên trong thẻ đoạn văn. Bỏ qua lỗi này thường dẫn đến lỗi hydration hoặc các thay đổi UI không mong muốn gây khó chịu cho người dùng.

Điều gì thực sự đang xảy raĐặc tả HTML5 định nghĩa phần tử <p> là một khung chứa văn bản. Nó chỉ chấp nhận "phrasing content" (nội dung cụm từ) — ví dụ như <span>, <strong>, hoặc <em>. Ngược lại, <div> là "flow content" (nội dung luồng), thuộc cấp khối. Khi trình duyệt thấy một thẻ <div> bên trong thẻ <p>, nó không chỉ hiển thị đơn thuần. Nó buộc thẻ đoạn văn phải đóng sớm ngay trước khi <div> bắt đầu. Điều này tạo ra sự sai lệch giữa Virtual DOM của React và cấu trúc thực tế của trình duyệt.

Nơi lỗi phát sinhĐoạn mã này chắc chắn sẽ kích hoạt cảnh báo:

const MyComponent = () => {
  return (
    <p>
      // Xem thông tin này:
      Check out this info:
      <div>Một số nội dung cấp khối ở đây</div>
    </p>
  );
};

Tại sao lỗi này xuất hiện- Mặc định của thư viện: Các bộ UI như Material UI (MUI) thường sử dụng component Typography, mặc định render thành thẻ <p>. Nếu bạn lồng một danh sách hoặc một hộp bên trong nó, console sẽ báo lỗi.- Trạng thái động: Bạn có thể có một đoạn văn hiển thị thông báo trạng thái hoặc một wrapper icon phức tạp dựa trên điều kiện.- Nội dung từ CMS: Sử dụng dangerouslySetInnerHTML để chèn dữ liệu cũ có thể dễ dàng khiến thẻ <div> lọt vào một khung chứa mà bạn cứ ngỡ chỉ là văn bản.## Cách sửa nhanh: Thay đổi khung chứaGiải pháp nhanh nhất thường là tốt nhất. Nếu bạn không nhất thiết phải dùng thẻ đoạn văn cho SEO, hãy đổi thẻ <p> bên ngoài thành <div> hoặc <section>. Điều này ngay lập tức giúp mã của bạn tuân thủ các tiêu chuẩn HTML.

// Đã sửa bằng cách sử dụng một khung chứa chung
const MyComponent = () => {
  return (
    <div>
      Check out this info:
      <div>Một số nội dung cấp khối ở đây</div>
    </div>
  );
};

Cách sửa chuẩn ngữ nghĩa: Chuyển sang thẻ SpanĐôi khi bạn cần thẻ đoạn văn đó để định dạng style. Trong trường hợp đó, hãy giữ thẻ <p> nhưng đảm bảo tất cả các phần tử con đều là inline (nội dòng). Thay thế thẻ <div> bên trong bằng <span> và áp dụng display: block trong CSS nếu bạn cần nó giữ giao diện như một khối.

// Lồng HTML hợp lệ với các thẻ span được định dạng kiểu block
const MyComponent = () => {
  return (
    <p>
      Check out this info:
      <span style={{ display: 'block' }}>
        // Bây giờ đã hợp lệ và sẽ không gây ra cảnh báo
        This is now valid and won't trigger warnings
      </span>
    </p>
  );
};

Next.js và "cơn ác mộng" HydrationCác framework SSR như Next.js khiến lỗi này đặc biệt nguy hiểm. Trong quá trình render ban đầu trên server, React tạo ra một chuỗi HTML mà div nằm trong p. Tuy nhiên, ngay khi HTML đó đến trình duyệt, trình duyệt sẽ tự động "sửa" nó. Khi React cố gắng tiếp quản ở phía client, DOM mà nó thấy không khớp với DOM mà nó đã gửi xuống. Điều này dẫn đến lỗi "Hydration Mismatch" đáng sợ, có thể gây tải trang chậm hoặc thậm chí khiến bố cục bị nhảy trong 0.5 giây khi trình duyệt cố gắng đồng bộ hai phiên bản.

Danh sách kiểm tra xác minh- Lưu file và để Hot Module Replacement (HMR) cập nhật lại trang.- Nhấn F12 để mở console và thực hiện làm mới trang hoàn toàn (hard refresh).- Xác nhận cảnh báo validateDOMNesting đã biến mất.- Nhấp chuột phải vào phần tử và chọn Inspect (Kiểm tra). Xác minh rằng trình duyệt không tự chèn các thẻ đóng "ma" (</p><p>) xung quanh nội dung của bạn.### Tham khảo nhanh: Cách lồng hợp lệ- <p> Chấp nhận: <span>, <a>, <button>, <strong>, <br>.- <p> Từ chối: <div>, <h1-h6>, <ul>, <section>, <p>.

Related Error Notes