Read CSV Files in React Apps without Installing Any Package
Tags: react, csv, javascript, parse
Published: 2021-06-13 11:24:45

This article covers how you can read any CSV file in your React app without the need for an npm package installation.

If you would prefer a video walkthrough, check it out on YouTube;

{% youtube l7Mpb4BpR7Y %}

To try this out you need a react app, you can use an existing one or create a new app with;

`npx create-react-app csv-reader`

After the app setup is complete, create a component in the src folder called `CsvReader.jsx`

Inside it we'll be adding a basic form that accepts a csv file input and sets it to a `csvFile` state, and a submit button that does nothing for now. The code should look like below;

```js
import { useState } from 'react'

export default function CsvReader(){
    const [csvFile, setCsvFile] = useState();
  
    return(
        <form id='csv-form'>
            <input
                type='file'
                accept='.csv'
                id='csvFile'
                onChange={(e) => {
                    setCsvFile(e.target.files[0])
                }}
            >
            </input>
            <br/>
            <button>
                Submit
            </button>
        </form>
    );

}
```

You can preview by plugging it into a page in your react app, I'll simply replace my app content with the csv reader component;

```js
import CsvReader from './CsvReader'
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <CsvReader />
      </header>
    </div>
  );
}

export default App;
```

Next, we add a submit button click handler, this addition will read the CSV file when the button is clicked using the `FileReader` objects and log the value of our csv file as text in the browser console.

```js
import { useState } from 'react'

export default function CsvReader(){
    const [csvFile, setCsvFile] = useState();
  
    const submit = () => {
        const file = csvFile;
        const reader = new FileReader();

        reader.onload = function(e) {
            const text = e.target.result;
            console.log(text);
        }

        reader.readAsText(file);
    }

    return(
        <form id='csv-form'>
            <input
                type='file'
                accept='.csv'
                id='csvFile'
                onChange={(e) => {
                    setCsvFile(e.target.files[0])
                }}
            >
            </input>
            <br/>
            <button
                onClick={(e) => {
                    e.preventDefault()
                    if(csvFile)submit()
                }}>
                Submit
            </button>
        </form>
    );

}
```

Finally I will be breaking the csv text into an array of objects with each column and row data as key value pairs;
imagine we have a csv like below;

|name| rank|age
| ----------- | ----------- | ----------- |
|Peter        |        Senior         |     21
|Joey         |        Junior         |     20
|Sarah        |        Veteran        |     33

I want to convert it into the following;

```js
[{name: "Peter", rank: "Senior", age: 21},
{name: "Joey", rank: "Junior", age: 20},
{name: "Sarah", rank: "Veteran", age: 33}]
```

To do this we need a function that takes the plain text read from the CSV, parses it and converts into the format above, then set it to a `csvArray` state which we create before writing the function;

```js
const [csvArray, setCsvArray] = useState([]);

const processCSV = (str, delim=',') => {
        const headers = str.slice(0,str.indexOf('\n')).split(delim);
        const rows = str.slice(str.indexOf('\n')+1).split('\n');

        const newArray = rows.map( row => {
            const values = row.split(delim);
            const eachObject = headers.reduce((obj, header, i) => {
                obj[header] = values[i];
                return obj;
            }, {})
            return eachObject;
        })

        setCsvArray(newArray)
    }
```

This function gets called after the `console.log` done in the submit handler

```js
const submit = () => {
        const file = csvFile;
        const reader = new FileReader();

        reader.onload = function(e) {
            const text = e.target.result;
            console.log(text);
            processCSV(text) // plugged in here
        }

        reader.readAsText(file);
    }
```

Finally we want to display the csv data in a table on our web page, we can do this by mapping the csvArray state into a table, our final `CsVReader` component should look like;

```js
import { useState } from 'react'

export default function CsvReader(){
    const [csvFile, setCsvFile] = useState();
    const [csvArray, setCsvArray] = useState([]);
    // [{name: "", age: 0, rank: ""},{name: "", age: 0, rank: ""}]
   
    const processCSV = (str, delim=',') => {
        const headers = str.slice(0,str.indexOf('\n')).split(delim);
        const rows = str.slice(str.indexOf('\n')+1).split('\n');

        const newArray = rows.map( row => {
            const values = row.split(delim);
            const eachObject = headers.reduce((obj, header, i) => {
                obj[header] = values[i];
                return obj;
            }, {})
            return eachObject;
        })

        setCsvArray(newArray)
    }

    const submit = () => {
        const file = csvFile;
        const reader = new FileReader();

        reader.onload = function(e) {
            const text = e.target.result;
            console.log(text);
            processCSV(text)
        }

        reader.readAsText(file);
    }

    return(
        <form id='csv-form'>
            <input
                type='file'
                accept='.csv'
                id='csvFile'
                onChange={(e) => {
                    setCsvFile(e.target.files[0])
                }}
            >
            </input>
            <br/>
            <button
                onClick={(e) => {
                    e.preventDefault()
                    if(csvFile)submit()
                }}
            >
                Submit
            </button>
            <br/>
            <br/>
            {csvArray.length>0 ? 
            <>
                <table>
                    <thead>
                        <th>Name</th>
                        <th>Age</th>
                        <th>Rank</th>
                    </thead>
                    <tbody>
                        {
                            csvArray.map((item, i) => (
                                <tr key={i}>
                                    <td>{item.name}</td>
                                    <td>{item.age}</td>
                                    <td>{item.rank}</td>
                                </tr>
                            ))
                        }
                    </tbody>
                </table>
            </> : null}
        </form>
    );

}
```
And when we upload a CSV and click submit, we should have a view like below;
![Final Web Page Result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cf0c4fplacn11hbj4rnt.png)

If you enjoyed this How-To article, please support by Subscribing to my youtube channel [https://www.youtube.com/channel/UCvF499ChQBnWb5ex162EiMg](#GeekSaw)