I am currently using react with node js in my application.
I am trying to read from a text file, get different errors when I try different things. With research, the easiest path to read from a file is using 'fs', so I'll post the two ways I tried to read from a local file (client side).
I would appreciate it if anyone could help solve my errors, or even show me a different way of reading from a local file!
import React ...
import { readFile, readFileSync } from 'fs';
// other imports
class Background extends Component {
// my constructor
componentDidMount() {
this.loadMe();
}
loadMe() {
var file = './read_file';
/* WAY 1: Asynchronously using readFile */
readFile(file, function(err, data) {
if (err) { console.log(err) }
console.log(data);
}
/* WAY 2: Synchronously using readFileSync */
var data = readFileSync(file);
console.log(data);
}
}
Obviously, I am not running both ways at the same time. I also essentially copied the code from other stack overflow answers and some tutorials online. I looked into FileReader
but couldn't make it work.
The error I am currently receiving: TypeError: Object(...) is not a function
pointing at var data = readFileSync(file);
Thank you!
To read a text file in React, we can use the FileReader constructor. to define the showFile function that gets the selected file from e. target.
below code is about how to read the file by react-native-fs on RN(React Native) project. ... // typescript style import * as RNFS from 'react-native-fs'; ... // readFile(filepath: string, encoding?: string) RNFS. readFile(filePath, 'ascii'). then(res => { ... }) .
fs
is a library reserved to server JS env like NodeJS.
It isn't possible to open and edit a file directly from the browser. It is, however, possible to open a file, edit and then download the edited file.
You need an input
element with file
type because this way the browsers can guarantee a page only accesses the files that the user explicitly selected. (Please tell me if this wasn't clear on the comments. I'll try to explain better if it wasn't.)
In the following example I'm going to use a textarea
element to edit the file's contents but you can change it in code or however you like, once you have the contents in a string variable.
<!DOCTYPE html>
<html>
<head>
<title>FileReader Example</title>
<meta charset="utf-8"/>
<script>
document.addEventListener('DOMContentLoaded',function() {
var fileInput = document.getElementById("fileInput");
var textArea = document.getElementById("fileEditor");
var saveFileButton = document.getElementById("saveFileButton");
var downloadAnchor = document.getElementById("downloadAnchor");
function base64EncodeUnicode(str) {
// First we escape the string using encodeURIComponent to get the UTF-8 encoding of the characters,
// then we convert the percent encodings into raw bytes, and finally feed it to btoa() function.
utf8Bytes = encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
return String.fromCharCode('0x' + p1);
});
return btoa(utf8Bytes);
}
function handleInputFileChange(event) {
//if we didnd't already have the "fileInput" var in scope, we could use "event.target" to get it
if(fileInput.files.length>=1) {
//In this example, I'm putting the selected file's name in the title. You don't need to do this
document.title = fileInput.files[0].name;
downloadAnchor.setAttribute("download","edited_"+fileInput.files[0].name);
}
else {
document.title = "FileReader Example";
downloadAnchor.setAttribute("download","edited_file.txt");
}
var fr = new FileReader();
fr.readAsText(fileInput.files[0]);
fr.onload = function (event) {
//Both "event.target.result" and "fr.result" contain the file's contents (because "event.target" is === "fr")
textArea.value = event.target.result;
// OR
//textArea.value = fr.result;
}
}
//The next is the fucntion returns a special kind of URL, a Data URL.
//These kind of URLs don't point to a file, they ARE the data.
//Read more here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
function getDownloadableTextAreaContents() {
return "data:text/plain,"+encodeURIComponent(textArea.value);
}
function onDownloadClick(event) {
//https://stackoverflow.com/a/247261/6302540
//var urlObject = "data:text/plain;base64,"+btoa(unescape(encodeURIComponent(textArea.value)));
var urlObject = getDownloadableTextAreaContents();
downloadAnchor.setAttribute("href",urlObject);
downloadAnchor.click();
}
fileInput.addEventListener("change",handleInputFileChange);
saveFileButton.addEventListener("click",onDownloadClick);
},false);
</script>
</head>
<body>
<h1>File Reader Example:</h1>
<input id="fileInput" type="file" accept=".txt"/>
<textarea name="File Editor" id="fileEditor" placeholder="Your file's contents will show up here once you select the file!"></textarea>
<button id="saveFileButton">Save File</button>
<!--The next <a> tag is just a trick to make the browser download a file. It isn't displayed (style="display: none;")-->
<a id="downloadAnchor" download="edited_file.txt" href="data:text/plain," style="display: none;"></a>
</body>
</html>
This is the example in plain JS but you can easily adapt this to react. A few of the adaptations are:
textarea
, you will have a controlled textarea
component. Setting and getting the value of the text area is easy with controlled components. (If you don't understand React's state and props or how controlled components work, you could use references (which make the React code pretty much the same and plain JS) but I seriously do not recommend it because it is an anti-pattern and should only be used in rare situations like some very, very,,,, very fancy animations);change
and click
events are easily converted using onChange
and onClick
props;downloadAnchor.click()
, you can follow this answer
<a>
)'s href
and download
attributes can also be a normal prop which has a state value, for example:In React:
<a download={this.state.downloadFilename} href={this.state.dataURL} style="display: none;"/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With