Reputation: 81
I built a super basic react app using the typescript version of create-react-app.
In my react app I want to display data from csv
files I have added my project. Imagine a data.csv
file under src
.
On a button click I want to trigger a function that reads this file, uses some of the data for calculations etc and then prints the result. What's the best way to make this happen? I know how to trigger a function on button click in React but don't know what to do within that function to read the file and console log the data to start.
Important - I already have the file path and file in my project and do not need user input to find the file
I tried using things like fs within the function but those throw errors and I learnt its because they are native modules and cant be used on browser. So what can be used for browser?
Upvotes: 7
Views: 18668
Reputation: 123
Since OP mentioned:
Important - I already have the file path and file in my project and do not need user input to find the file
it will be better to pre-read the file and have its content available already in the app. This will avoid the need of doing any fetch
at run time and will improve the performance.
To do this, we'll have to configure webpack
.
This can be done in the following way:
Install react-app-rewired
so that we can modify webpack.config.js
.
Have a rule added to webpack.config.js
(indirectly, via the above package) for loading the content of the csv
file when we run npm start
or npm run build
.
Import the csv
file in the React component script and use its content.
Explained in detail below.
react-app-rewired
Check the documentation here - https://github.com/timarney/react-app-rewired.
Basically, we have to:
npm install [email protected] --save-dev
flip the start
, build
, test
commands in package.json
like this:
- "start": "react-scripts start",
+ "start": "react-app-rewired start",
config-overrides.js
Create a file called config-overrides.js
in the project's root directory, and add there:
module.exports = function override(config, env) {
config.module.rules = [
...config.module.rules,
{
resourceQuery: /raw/,
type: 'asset/source',
generator: { emit: false, }
},
{
test: /\.csv$/,
loader: 'csv-loader',
type: 'asset/source',
options: {
dynamicTyping: true,
header: true,
skipEmptyLines: true
},
generator: { emit: false }
}
]
return config;
}
Note: The first rule above will help us read the file as plain text, while the next one will parse it for us (provided we have installed csv-loader
).
Use whichever is required as per the need.
csv
file in React scriptconst csv = require('./filename.csv?raw'); // we get string
// or
const csv = require('./filename.csv'); // we get json
// Use the csv variable wherever needed
Upvotes: 1
Reputation: 6055
fs
only works on the server, not on the client. The browser doesn't have (general) access to the file system.
There are several options:
Put the .csv file into the public
folder, then you can load it like:
function App() {
const [ text, setText ] = useState();
const load = function(){
fetch( './csvInPublicFolder.csv' )
.then( response => response.text() )
.then( responseText => {
setText( responseText );
})
};
return (
<div>
<button onClick={ load }>load</button>
<h2>text:</h2>
<pre>{ text }</pre>
</div>
);
}
Or, if the file has to be inside the src
folder,
yarn add file-loader --dev
webpack.config.js
:module.exports = {
module: {
rules: [
{
test: /\.csv$/,
use: [
{
loader: 'file-loader',
},
],
},
],
},
};
import csvFilePath from './csvInSrcFolder.csv';
import { useState } from 'react';
function App() {
const [ text, setText ] = useState();
const load = function(){
fetch( csvFilePath )
.then( response => response.text() )
.then( responseText => {
setText( responseText );
});
};
return (
<div>
<button onClick={ load }>load</button>
<h2>text:</h2>
<pre>{ text }</pre>
</div>
);
}
Or you can create a custom server.js and send a request to the server. On the server you have access to the file system (fs
).
if you don't want to parse the file content yourself, you can use an existing csv parser. Some people recommend papaparse (I don't have own experience about which ones are good)
import * as Papa from 'papaparse';
// ...
fetch( csvFilePath )
.then( response => response.text() )
.then( responseText => {
// -- parse csv
var data = Papa.parse(responseText);
console.log('data:', data);
});
Upvotes: 7