DEV Community

Cover image for Read CSV Files in React Apps without Installing Any Package
Nurudeen Amedu
Nurudeen Amedu

Posted on • Updated on

Read CSV Files in React Apps without Installing Any Package

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;

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;

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>
    );

}
Enter fullscreen mode Exit fullscreen mode

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;

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

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

export default App;
Enter fullscreen mode Exit fullscreen mode

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.

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>
    );

}
Enter fullscreen mode Exit fullscreen mode

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;

[{name: "Peter", rank: "Senior", age: 21},
{name: "Joey", rank: "Junior", age: 20},
{name: "Sarah", rank: "Veteran", age: 33}]
Enter fullscreen mode Exit fullscreen mode

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;

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)
    }
Enter fullscreen mode Exit fullscreen mode

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

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);
    }
Enter fullscreen mode Exit fullscreen mode

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;

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>
    );

}
Enter fullscreen mode Exit fullscreen mode

And when we upload a CSV and click submit, we should have a view like below;
Final Web Page Result

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

Oldest comments (12)

Collapse
 
hannahgooding profile image
Hannah Gooding

I found this really helpful - thank you!

Collapse
 
theallegrarr profile image
Nurudeen Amedu

You’re welcome

Collapse
 
adeldegan profile image
Al Del Degan

This was super useful, you saved me a lot of coding. Thanks!

Collapse
 
omogbai profile image
Omogbai Atakpu

This was very helpful, thank you Nurudeen!

Collapse
 
alarbelaez profile image
alarbelaez

I had problems with the breaks and the cvsArray, can you help me

Collapse
 
theallegrarr profile image
Nurudeen Amedu

What’s the error you’re getting?

Collapse
 
alarbelaez profile image
alarbelaez

TypeError: csvArray is undefined

Collapse
 
theallegrarr profile image
Nurudeen Amedu

Check for csvArray before using it, you can put everything inside an if block

if(csvArray){
// continue
}

Collapse
 
agusgarcia3007 profile image
Agustin Garcia

This is exactly what I was looking for! thank you so much :)))

Collapse
 
agusgarcia3007 profile image
Agustin Garcia

hey! could you solve the extra blank item in rows bug? I'm having the same problem

0: {name: 'joey', age: '21', rank: 'senior'}
1: {name: 'amanda', age: '28', rank: 'mid'}
2: {name: 'peter', age: '24', rank: 'junior'}
3: {name: '', age: undefined, rank: undefined

Collapse
 
theallegrarr profile image
Nurudeen Amedu

It could be due to a blank row in your csv, but it can be solved by checking the final data for undefined values and removing the row

Collapse
 
nkrgangavaram profile image
nkrgangavaram

Heyy it was a great solution...can we get the same thing without using input type as file. Can you please help me with other ways..