Building a React File Upload Button to Parse JSON and YAML

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:

TSX
<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:

TSX
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.

TSX
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.

TSX
{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.

Share this:

Leave a Reply