Vấn đề phát sinh từ đâuCó lẽ bạn đang xây dựng một component có thể tái sử dụng hoặc định dạng style bằng một thư viện như styled-components. Mọi thứ trông vẫn ổn trên giao diện người dùng (UI), nhưng console của trình duyệt lại đang "than phiền". Điều này xảy ra khi một prop vốn dành cho logic hoặc style bị "rò rỉ" xuống phần tử HTML thực tế. React nhìn thấy một thuộc tính tùy chỉnh mà nó không nhận diện được và lo ngại rằng bạn đang mắc lỗi.
Hãy xem qua một thiết lập điển hình sử dụng styled-components:
import styled from 'styled-components';
const NavItem = styled.a`
color: ${props => (props.isActive ? '#007bff' : '#6c757d')};
`;
// Cách sử dụng
const Sidebar = () => (
<NavItem href="/home" isActive={true}>
Home
</NavItem>
);
Khi component này render, React cố gắng gắn isActive trực tiếp vào thẻ <a>. Vì isActive không phải là một thuộc tính HTML tiêu chuẩn, bạn sẽ nhận được cảnh báo sau:
Warning: React does not recognize the `isActive` prop on a DOM element...
Gốc rễ của vấn đềKể từ phiên bản 16.1, React đã trở nên khắt khe hơn với các thuộc tính DOM. Các phần tử tiêu chuẩn như <div> hay <button> chỉ chấp nhận các thuộc tính HTML hợp lệ như id, className, hoặc href. Nếu bạn truyền một thứ gì đó khác, React sẽ coi đó là một sai sót trừ khi bạn thêm tiền tố data- hoặc aria-.
Khi bạn sử dụng styled-components hoặc rải props ({...props}), React cố gắng ghi mọi prop vào HTML. Trình duyệt không biết phải làm gì với <a isActive="true">. Điều này tạo ra tình trạng "ô nhiễm DOM" (DOM pollution) và đôi khi có thể gây ra gánh nặng hiệu năng nhỏ trong các ứng dụng quy mô lớn với hàng nghìn node.
Giải pháp tốt nhất: Transient PropsNếu bạn sử dụng styled-components (v5.1 trở lên), giải pháp gọn gàng nhất là Transient Props. Chỉ cần thêm tiền tố dấu đô la ($) vào prop của bạn. Điều này thông báo cho thư viện sử dụng prop đó để định dạng style nhưng sẽ loại bỏ nó trước khi HTML được render.
Cách triển khai:```
import styled from 'styled-components';
// Sử dụng tiền tố $ cho các prop chỉ dùng để định dạng style
const NavItem = styled.a color: ${props => (props.$isActive ? 'blue' : 'gray')};;
const Sidebar = () => ( // Truyền prop với tiền tố $ <NavItem href="/home" $isActive={true}> Home );
Bằng cách chuyển sang `$isActive`, prop này chỉ nằm trong logic CSS của bạn. Nó không bao giờ xuất hiện trong DOM, giúp HTML của bạn luôn hợp lệ và console sạch sẽ.
## Giải pháp thay thế: Lọc Prop thủ côngCó thể bạn không sử dụng thư viện CSS-in-JS, hoặc bạn đang bọc (wrap) một component một cách thủ công. Trong những trường hợp này, hãy sử dụng kỹ thuật destructuring để tách biệt logic tùy chỉnh của bạn khỏi các thuộc tính tiêu chuẩn. Điều này đảm bảo chỉ các prop hợp lệ mới được đưa vào phần tử.
### Ví dụ:```
const CustomButton = (props) => {
// Tách isActive ra, sau đó gom tất cả những thứ còn lại vào 'domProps'
const { isActive, children, ...domProps } = props;
return (
<button
{...domProps}
style={{ fontWeight: isActive ? '700' : '400' }}
>
{children}
</button>
);
};
Ở đây, isActive được sử dụng cho logic nhưng bị loại trừ khỏi {...domProps}. Thẻ <button> hoàn toàn không "biết" về sự tồn tại của prop tùy chỉnh này.
Nâng cao: API 'shouldForwardProp'Đôi khi bạn không thể dễ dàng đổi tên các prop để sử dụng tiền tố $. Đối với các component phức tạp, styled-components và Emotion cung cấp bộ lọc shouldForwardProp. Điều này giúp bạn kiểm soát chi tiết những gì được phép truyền xuống trình duyệt.
Ví dụ:```
import styled from 'styled-components'; import isPropValid from '@emotion/is-prop-valid';
const Container = styled.div.withConfig({
shouldForwardProp: (prop) => isPropValid(prop) && prop !== 'isActive',
}) padding: ${props => props.isActive ? '20px' : '10px'};;
Tiện ích `@emotion/is-prop-valid` là một công cụ hỗ trợ nhỏ (khoảng 8KB) giúp kiểm tra xem một chuỗi có phải là thuộc tính HTML tiêu chuẩn hay không. Việc thêm `prop !== 'isActive'` sẽ chặn cụ thể prop đó không bị rò rỉ.
## Cách xác minh giải pháp
- **Kiểm tra Console:** Xóa nhật ký (logs) và tải lại trang. Cảnh báo màu vàng sẽ biến mất.
- **Kiểm tra DOM:** Nhấp chuột phải vào phần tử của bạn trong trình duyệt và chọn 'Inspect' (Kiểm tra). Kiểm tra thẻ. Bạn sẽ thấy `<a href="/home">` mà không có bất kỳ thuộc tính `isActive` nào đi kèm.
- **Kiểm tra UI:** Đảm bảo các style của bạn vẫn hoạt động. Nếu bạn đã sử dụng `$isActive`, hãy chắc chắn rằng CSS tham chiếu chính xác đến tên mới đó.
## Tóm tắt nhanhCảnh báo "React does not recognize prop" chỉ là một lớp bảo vệ an toàn cho HTML của bạn. Để khắc phục nhanh chóng:
- Sử dụng **Transient Props** (`$propName`) cho `styled-components`.
- **Destructure** các prop của bạn để tách biệt logic tùy chỉnh khỏi `...rest`.
- Áp dụng **shouldForwardProp** để lọc tự động và nâng cao.

