React and file uploads: reading a CSV file

React and file uploads: reading a CSV file

In this article we'll take a closer look at how to handle file uploads in React by reading the contents of a CSV file and display them on the page.

In this article we'll take a closer look at how to handle file uploads in React by reading the contents of a CSV file and display them on the page.

We start by defining an upload form as a simple React component that accepts a function as a prop. This function will handle the CSV file when a user chooses one.

function UploadForm({ handleFileUpload }) {
    return (
        <form className="form" method="post" action="">
            <div className="file-wrap">
                <label htmlFor="file">Choose file
                    <input type="file" onChange={(e) => handleFileUpload(e)} id="file" accept=".csv" />
                </label>
            </div>
        </form>
    )
}

export default UploadForm;

Notice how we're listening to the change event and also using the event object in order to get access to the underlying DOM element because we need it to use the HTML5 File API.

We can now define the component which is responsible to create the HTML table that will contain the actual CSV data.

function DataTable({ rows }) {
    return (
        <div className="result">
            <table>
                <thead>
                <tr>
                    <th>Name</th>
                    <th>Age</th>
                    <th>Address</th>
                </tr>
                </thead>
                <tbody>
                {rows.map((row, index) => (

                    <tr key={index}>
                        <td>{row.name}</td>
                        <td>{row.age}</td>
                        <td>{row.address}</td>
                    </tr>
                ))}
                </tbody>
            </table>
        </div>
    )
}

export default DataTable;

Here we're simply iterating through the rows prop and accessing to the object that represents a single row datum.

In our main component, App, we first have to define a state property that will contain the rows obtained from the CSV file:

import UploadForm   from "./UploadForm";
import DataTable from "./DataTable";
import { useState } from "react";

function App() {
    const [rows, setRows] = useState([]);
    // Main functions here
    return (
    <main className="app">
        <h1>React: CSV file upload</h1>
        <UploadForm handleFileUpload={handleFileUpload} />
        {rows.length > 0 && <DataTable rows={rows} />}
    </main>
  );
}

export default App;

The logical condition put at the end of the main container will insert our data table only when the rows array is not empty. In order to fill this array, we need to use the JavaScript FileReader object to read the text contents of the CSV file by accessing the files array of the form element. Then we have to split such contents into lines and turn them into an array of objects.

const parseCSV = csv => {
        const lines = csv.split('\n');
        const rows = lines.slice(1);
        const data = [];
        for(const row of rows) {
            const values = row.split(',');
            data.push({
                name: values[0],
                age: values[1],
                address: values[2]
            });
        }
        return data;
    };

    const handleFileUpload = event => {
        const file = event.target.files[0];
        const reader = new FileReader();
        reader.onload = event => {
            const csv = event.target.result;
            const data = parseCSV(csv);
            setRows(data);
        };
        reader.readAsText(file);
    };

The actual reading operation is done by using the onload event handler which gives us access to the result property. This property contains all the contents of the CSV file as a string.

Since a CSV file can be split into an array of lines with the new line character (\n) and then each line can be in turn split into an array of values with the , separator, we actually only need to loop through this structure and select the appropriate values that we want to insert into our rows array.

As you can see, JavaScript already provides us with all the required APIs to get this task done.