What happens when you paste
When a user pastes content with Ctrl+V or Command+V, React fires a ClipboardEvent. This event contains a clipboardData
property that gives you access to everything that was copied.
The clipboardData
object has these main properties:
items
: A collection of everything in the clipboardfiles
: Any files present in the clipboardtypes
: Format strings like "text/plain" or "image/png"
Clipboard data structure
Each item in the clipboard has:
A
kind
property: Either "string" or "file"A
type
property: The MIME type such as "image/png" or "text/plain"
More complete example with file handling
This example handles multiple image pastes and shows file information:
import React, { useState, useEffect, useRef } from "react";
interface PastedFile {
url: string;
name: string;
type: string;
size: number;
file: File;
}
const ImagePasteInput: React.FC = () => {
const [pastedFiles, setPastedFiles] = useState<PastedFile[]>([]);
const [inputValue, setInputValue] = useState("");
const inputRef = useRef<HTMLInputElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
// Set up paste event listener on the document
useEffect(() => {
const handlePaste = (event: ClipboardEvent) => {
// Check if our input element is focused
if (document.activeElement !== inputRef.current) return;
const items = event.clipboardData?.items;
if (!items) return;
// Process image files
const newFiles: PastedFile[] = [];
Array.from(items).forEach((item) => {
if (item.kind === "file" && item.type.startsWith("image/")) {
const file = item.getAsFile();
if (file) {
newFiles.push({
url: URL.createObjectURL(file),
name: file.name || `pasted-image-${Date.now()}.png`,
type: file.type,
size: file.size,
file: file,
});
}
}
});
if (newFiles.length > 0) {
setPastedFiles((prev) => [...prev, ...newFiles]);
event.preventDefault(); // Prevent pasting text into input
}
};
document.addEventListener("paste", handlePaste);
return () => {
document.removeEventListener("paste", handlePaste);
};
}, []);
// Clean up object URLs on unmount
useEffect(() => {
return () => {
pastedFiles.forEach((file) => URL.revokeObjectURL(file.url));
};
}, [pastedFiles]);
const handleRemoveFile = (index: number) => {
setPastedFiles((prev) => {
const newFiles = [...prev];
URL.revokeObjectURL(newFiles[index].url);
newFiles.splice(index, 1);
return newFiles;
});
};
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(event.target.value);
};
const handleUpload = () => {
// Example function to handle the upload of pasted files
console.log(
"Files to upload:",
pastedFiles.map((file) => file.file)
);
// Here you would typically send these files to your server
};
return (
<div ref={containerRef}>
<div style={{ marginBottom: "20px" }}>
<label htmlFor="pasteInput">
Paste images here (click and press Ctrl+V):
</label>
<input
ref={inputRef}
id="pasteInput"
type="text"
value={inputValue}
onChange={handleInputChange}
placeholder="Click here and paste images with Ctrl+V"
style={{
display: "block",
width: "100%",
padding: "8px",
border: "1px solid #ccc",
borderRadius: "4px",
marginTop: "5px",
}}
/>
</div>
{pastedFiles.length > 0 && (
<div>
<h3>Pasted Images:</h3>
<div style={{ display: "flex", flexWrap: "wrap", gap: "10px" }}>
{pastedFiles.map((file, index) => (
<div
key={index}
style={{
border: "1px solid #eee",
padding: "10px",
borderRadius: "4px",
}}
>
<img
src={file.url}
alt={file.name}
style={{ maxWidth: "200px", maxHeight: "200px" }}
/>
<div>Type: {file.type}</div>
<div>Size: {Math.round(file.size / 1024)} KB</div>
<button
onClick={() => handleRemoveFile(index)}
style={{ marginTop: "5px", padding: "4px 8px" }}
>
Remove
</button>
</div>
))}
</div>
<button
onClick={handleUpload}
style={{
marginTop: "20px",
padding: "8px 16px",
backgroundColor: "#4285f4",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer",
}}
>
Upload Images
</button>
</div>
)}
</div>
);
};
export default ImagePasteInput;
Things to remember
The clipboard can contain different types of content:
Plain text
Rich text or HTML
Images from screenshots or copied content
Files from explorer/finder
Mixed content with multiple formats
When someone pastes an image:
It appears as a file-like object in the clipboard
It has a MIME type like "image/png" or "image/jpeg"
You use
item.getAsFile()
to get a File objectYou can create an object URL to display it
Common clipboard scenarios include:
Screenshots creating "image/png" items
Web images often creating multiple clipboard items
Images from editors coming with their appropriate MIME type