Handling file uploads in a React app is straightforward, but things get more interesting when you need to filter for specific file types and parse their contents. I needed to create an upload button that only accepted JSON and YAML files, then read and displayed their contents in the browser. Here’s how I did it.
Thank me by sharing on Twitter 🙏
Setting Up the File Input
The standard <input type="file">
element works well for uploads, but I wanted a clean, styled button instead of a visible file picker. The trick is to hide the input and use a <label>
styled as a button. That way, clicking the label triggers the file selection.
Here’s how I set it up:
<input
type="file"
accept=".json,.yaml,.yml"
onChange={handleFileUpload}
id="fileInput"
style={{ display: "none" }}
/>
<label
htmlFor="fileInput"
style={{
display: "inline-block",
padding: "10px 16px",
backgroundColor: "#007bff",
color: "#fff",
borderRadius: "5px",
cursor: "pointer",
fontSize: "16px",
textAlign: "center",
}}
>
Upload JSON or YAML
</label>
Now, when a user clicks the button, the file picker opens, but the input remains hidden.
Filtering for JSON and YAML Files
Not all uploaded files should be processed. To enforce this, I checked the file’s extension before reading it:
Logitech Brio 101 Full HD 1080p Webcam Made for Meetings and Works for Streaming — Auto-Light Balance, Built-in Mic, Privacy Shutter, USB-A, for Microsoft Teams, Google Meet, Zoom, and More - Black
$24.99 (as of March 13, 2025 13:36 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)The Technological Republic: Hard Power, Soft Belief, and the Future of the West
$22.51 (as of March 13, 2025 13:36 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)Anker USB to USB C Cable [2 Pack, 6FT], USB A to USB C Charger Cord for Samsung Galaxy S10 S10+, LG V30, Beats Fit Pro and More (USB 2.0, Black)
$9.99 (as of March 13, 2025 13:36 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)const handleFileUpload = (event) => {
const file = event.target.files[0];
if (!file) return;
const fileExtension = file.name.split(".").pop().toLowerCase();
if (!["json", "yaml", "yml"].includes(fileExtension)) {
setError("Invalid file type. Please upload a JSON or YAML file.");
return;
}
readFile(file, fileExtension);
};
This ensures that only JSON or YAML files are processed. If a user selects something else, they see an error message instead of unexpected behavior.
Reading and Parsing File Contents
Once a valid file is selected, it needs to be read and parsed. I used the FileReader
API to read the contents as text. Then, based on the file extension, I parsed it as either JSON or YAML.
import yaml from "js-yaml";
const readFile = (file, fileExtension) => {
const reader = new FileReader();
reader.onload = (e) => {
try {
const content = e.target.result;
let parsedData;
if (fileExtension === "json") {
parsedData = JSON.parse(content);
} else {
parsedData = yaml.load(content);
}
setParsedData(parsedData);
setError("");
} catch {
setError("Error parsing the file. Please check its format.");
}
};
reader.readAsText(file);
};
This approach ensures that JSON files are parsed with JSON.parse
, while YAML files use the js-yaml
library.
Displaying the Parsed Data
To make the parsed data easy to read, I formatted it with JSON.stringify
and displayed it inside a styled <pre>
element.
{parsedData && (
<div
style={{
marginTop: "20px",
padding: "10px",
backgroundColor: "#f4f4f4",
borderRadius: "5px",
whiteSpace: "pre-wrap",
wordWrap: "break-word",
fontFamily: "monospace",
}}
>
<strong>Parsed Data:</strong>
<pre>{JSON.stringify(parsedData, null, 2)}</pre>
</div>
)}
Now, when a user uploads a valid JSON or YAML file, its contents appear in a readable format on the page.
Wrapping It Up
With this setup, I now have a React component that allows users to upload JSON and YAML files, filters out invalid files, parses their contents, and displays the results. By using a hidden file input and a styled label, the UI remains clean and intuitive. Whether working with configuration files or structured data, this approach makes handling file uploads simple and effective.