Read CSV Files in React Apps without Installing Any Package

Nurudeen Amedu - Jun 13 '21 - - Dev Community

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

. . . . . . .
Terabox Video Player