tezvyn:

Handling File Uploads in React

AI-drafted, machine-checkedSource: nextjs.orgintermediate

Treat a file input like a remote control for the browser's file picker. React can't hold the file data directly in state, but it can grab a reference to the selected file and send it to a server using a `FormData` object.

WHY IT EXISTS: Modern web applications often need to accept files from users, such as images for profiles, documents for submission, or data for import. Browsers provide a standard <input type="file"> element, but integrating this into a declarative, state-driven framework like React requires a specific pattern to bridge the imperative browser API with React's component model.

THE MENTAL MODEL: Think of a file input as an "uncontrolled component" by nature. Unlike a text input where you can programmatically set its value from React state, you cannot force a file input to select a specific local file for security reasons. React's role is to render the input, which triggers the browser's file picker, and then handle the file(s) the user selects via an onChange event. You manage a reference to the file, not the file's raw content, in your component's state.

HOW IT WORKS: You render a standard <input type="file" /> in your component and attach an onChange event handler. When the user selects a file, this handler receives an event e. The selected files are available in a FileList object at e.target.files. You can then take the first file, e.target.files[0], and store this file object in your component's state. To upload it, you create a new FormData object, append the file using a key-value pair like formData.append('userAvatar', fileFromState), and send this formData object as the body of a POST request to your server.

WHEN TO USE IT: This pattern is essential any time a user needs to upload a file from their local device to your server. Common use cases include uploading a profile picture, attaching a resume to a job application, importing a CSV file for data processing, or submitting images to a gallery.

WHEN NOT TO USE IT: This specific flow is for user-selected files. If you are generating file-like data within the browser itself (e.g., creating a PDF or capturing a canvas as an image blob), you might not use the <input> element. However, you would still likely use the FormData API to send that generated blob to the server.

ONE CANONICAL EXAMPLE: A user settings page allows changing a profile picture. The component has state for the file: const [avatarFile, setAvatarFile] = useState(null);. The JSX contains <input type="file" accept="image/*" onChange={(e) => setAvatarFile(e.target.files[0])} />. On form submission, a handler checks if avatarFile exists, creates a FormData object, appends the file with formData.append('avatar', avatarFile), and then POSTs it to the /api/user/avatar endpoint.

Read the original → nextjs.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.