Spread operator trong JSX là cú pháp {...object} để bung tất cả key-value của một object ra thành các props riêng lẻ truyền vào component.
Khi viết <Button {...btnProps} />, JSX compiler chuyển thành React.createElement(Button, btnProps). Nếu có key trùng, props viết trực tiếp trên component luôn thắng props từ spread, vì chúng được gán sau cùng trong quá trình merge.
const btnProps = { color: "blue", disabled: true, type: "submit" };
// Spread:
<Button {...btnProps} />
// Tương đương viết tay:
<Button color="blue" disabled={true} type="submit" />
// Override — disabled bên ngoài thắng:
<Button {...btnProps} disabled={false} /> // disabled = falseTrường hợp phổ biến nhất là wrapper component — bạn nhận props từ bên ngoài, cần forward phần lớn xuống element con mà không liệt kê từng cái:
function TextInput({ label, ...inputProps }) {
return (
<label>
{label}
<input {...inputProps} />
</label>
);
}
// Gọi:
<TextInput label="Email" type="email" placeholder="abc@xyz.com" />Ở đây type và placeholder lọt qua ...inputProps xuống <input> tự nhiên.
Lỗi thường gặp:
- Leak props xuống DOM: Nếu spread một object chứa key mà element HTML không nhận (ví dụ customClass), React sẽ cảnh báo "Unknown prop" trên console. Nếu dùng custom attribute, gắn tiền tố data- để hợp lệ.
- Ghi đè ngoài ý muốn: Props viết sau spread sẽ override props bên trong — đôi khi bạn vô tình ghi đè mà không nhận ra.
- Độ ưu tiên merge: Không có cơ chế "deep merge" — spread chỉ shallow copy. Object lồng nhau sẽ bị thay thế toàn bộ, không merge từng key.
Lưu ý: Khi cần forward ref kèm props, dùng React.forwardRef kết hợp spread, không dùng innerRef hay prop tương tự vì đó là pattern cũ không còn hỗ trợ.