reactJS and reading a text file - javascript

I have a reactJS application where I need to read in a large text file and use the data from the file to populate some arrays. I came across some code examples and I am trying to implement this code:
readTextFile = file => {
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = () => {
if (rawFile.readyState === 4) {
if (rawFile.status === 200 || rawFile.status == 0) {
var allText = rawFile.responseText;
console.log("allText: ", allText);
this.setState({
fundData: allText
});
}
}
};
rawFile.send(null);
};
The code is called by executing this line of code:
this.readTextFile("../text/fund_list.txt");
When I execute the application, I get the following error message:
GET http://localhost:8080/text/fund_list.txt 404 (Not Found)
This is what my application structure looks like:
The readTextFile function is in the account_balanc.js code and I am trying to read in the text file /text/fund_list.txt. The file does exist so obviously I am not referencing the file correctly but I don't know why.
I have tried this.readTextFile("../text/fund_list.txt") and this.readTextFile("./text/fund_list.txt"); but neither worked. I even tried moving fund_list.txt into the /screens folder and changing the function call to this.readTextFile("fund_list.txt"); but I still get the 404 error message.
Any ideas why?
Thank you.

I moved the fund_list.txt file into the public/text folder (after I created it) and changed the calling of the function to this.readTextFile("./text/fund_list.txt");
I saw this as a posted solution but then the post was removed (I don't know why) so I can't thank the user who posted it. But this solved my problem.

You can use webpack raw loader and directly import the .txt file into the component.
First, install raw-loader:
npm i -D raw-loader
Second, add the loader to your webpack config:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
}
]
}
}
Then, directly import .txt to your component:
import txt from './file.txt';

I'm assuming you are using Webpack as the bundler.
The reason you were getting a 404 Not Found is because you need to configure Webpack to bundle the file into the build folder the website is hosting.
Moving it to the /public folder worked because Webpack was configured to bundle all the files in the /public folder as it is usually the entry point of the project (since this is probably create-react-app).
Also the folks at create-react-app are smart and saw that if it was a .txt extension file, they would bundle them into a /text folder in the build file, just as any .jpg or .png files will bundle into a /images folder.
Note that a lot of files need a special webpack loader if you import them in project, but you can also use a webpack plugin to copy the file into your bundle and then read that programmatically as you are doing.
Therefore once you moved it to that folder your application could actually find it in the build folder -hosted in localhost:8080 !

Using HTML5 FileReader API you can easily read any file. Please have look at the following code:
function App() {
const [json, setJson] = useState("");
let fileInputRef = React.createRef();
return (
<div className="App">
<p>{json}</p>
<input
type="file"
ref={fileInputRef}
style={{ display: "none" }}
onChange={async e => {
const reader = new FileReader();
reader.onload = function() {
const text = reader.result;
setJson(text);
};
reader.readAsText(e.target.files[0]);
}}
accept=".json,application/json"
/>
<button
onClick={() => {
fileInputRef.current.click();
}}
>
Upload JSON file
</button>
</div>
);
}
Here is a working Demo

I don't have a lot of experience with pure javascript applications, I usually use a rails backend, but I would recommend focusing on just being able to hit http://localhost:8080/text/fund_list.txt in a browser and get a response. Once you solve that it looks like the javascript will do it's thing.

Try...
const file = require("../text/fund_list.txt");
Then
this.readTextFile(file);

Related

Webpack 5 IgnorePlugin - Not ignoring JS file from output on CSS files only?

I am trying to use the Webpack's IngorePlugin. I am using my Webpack file only to create a CSS file. On build, it outputs a JS file. But I don't want that. Tried ignoring JS files but still outputs it.
new webpack.IgnorePlugin(/^\.\/js\/(?!admin)/),
Outputs in the ROOT folder. So I want to disable all JS files from the output in the root folder. "admin" is the file being created.
How can I do this?
To properly answer your question, it'd be helpful if you posted a link to the full WP config file and an example of the file that's being processed.
Also, you mentioned you're only using WP to create a CSS file, does that mean you're just trying to use something like SASS, Stylus, Less, etc? If so, you could probably just set up a package.json script to compile your CSS without WP.
For example, if you have a .scss file, you could install node-sass, and create a simple Node script to compile what file you pass in as an arg.
bin/
- build-css.js
src/
- styles.sass
Within build-css.js
#!/usr/bin/env node
const { basename, resolve } = require('path');
const sass = require('node-sass');
const [...files] = process.argv.slice(2);
if (files.length) {
files.forEach((relativeFilePath) => {
const fileName = basename(relativeFilePath, '.scss');
sass.render(
{
file: resolve(__dirname, relativeFilePath),
outFile: resolve(__dirname, `./public/css/${fileName}.css`),
},
(err, result) => { console.log(err); }
);
});
}
else {
console.log('No files were provided to process');
}
Within package.json
"scripts": {
"build:css": "node ./bin/build-css.js"
}
The above has the benefit of giving you the control of how your files are processed at a more granular level, and you're only locked in to any SCSS changes, instead of Webpack and SCSS.
If you're using WP for it's file watching capabilities, you could instead wire up chokidar to run the new script when you change files.

Webpack Externals , load a local file on runtime

I have a file uiConfig.json, it has some server URL, and the DevOps team changes the files based on the environment.
`
I am trying to load this file on runtime using webpack.
So far I have tried the following.
Using Webpack Externals
//webpack.config.js
externals: {
'uiConfig': JSON.stringify(require('./uiConfig.json'))
},
copied uiConfig at root path of build directory
//app.js
import uiConfig from 'uiConfig'
Fetching the uiConfig from the script tag and exposing the url to global window object.
This method seems to be working sometimes, but its not consistent
<script type="application/javascript">
window.uiConfig = {}
fetch('./uiConfig.json').then((response) => {
return response.json();
}).then((data) => {
window.uiConfig = data
})
</script>
What am I doing wrong, how could I tackle this problem?
Appreciate your help.

system.js build config for pdf.js

I'm trying to build pdf.js in order to embed the viewer into an app I'm working on.
I want to build the viewer by hand so it can be included in the application that is getting packaged by webpack.
The application entrypoint, index.js, has the line
import viewer from 'pdfjs-dist/web/pdf_viewer';
This results in the viewer being included in the transpiled app code, however the pdf.js viewer uses System.js to load modules that it needs to run.
In the compiled version that Mozilla serves, the code has been transpiled to not use System.js; see view-source:https://mozilla.github.io/pdf.js/web/viewer.js in the the webViewerLoad function on line 3774.
function webViewerLoad() {
var config = getViewerConfiguration();
window.PDFViewerApplication = pdfjsWebApp.PDFViewerApplication;
pdfjsWebApp.PDFViewerApplication.run(config);
}
This differs from the non-transpiled source that can be found on https://github.com/mozilla/pdf.js/blob/master/web/viewer.js#L178, and the source map for the Mozilla hosted viewer retains these SystemJS lines.
function webViewerLoad() {
let config = getViewerConfiguration();
if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) {
Promise.all([
SystemJS.import('pdfjs-web/app'),
SystemJS.import('pdfjs-web/genericcom'),
SystemJS.import('pdfjs-web/pdf_print_service'),
]).then(function([app, ...otherModules]) {
window.PDFViewerApplication = app.PDFViewerApplication;
app.PDFViewerApplication.run(config);
});
} else {
window.PDFViewerApplication = pdfjsWebApp.PDFViewerApplication;
pdfjsWebApp.PDFViewerApplication.run(config);
}
}
What I want to know is how this was achieved, and how to replicate the configuration to build this.
The production viewer.js has been compiled with webpack. In gulpfile.js you will find the following block:
function createWebBundle(defines) {
var viewerOutputName = 'viewer.js';
var viewerFileConfig = createWebpackConfig(defines, {
filename: viewerOutputName,
});
return gulp.src('./web/viewer.js')
.pipe(webpack2Stream(viewerFileConfig));
}
In my case I simply installed pdfjs-dist and imported pdfjs-dist/web/pdf_viewer. Building with webpack worked fine. Getting the web worker to work right required some extra effort.

Browserify: Uncaught error when requiring js file by path created from string concatenation

I am using browesify for client side app. I have files maps.js and directions.js sitting besides my index.js file, and inside my index.js, I have a function getPageName() which returns the name of the file that I should "require". When I try to do
var pageName = getPageName();
var page;
if (pageName === 'maps') {
page = require('./maps');
} else if (pageName === 'directions') {
page = require('./directions');
}
it works fine. But when I instead try to use following trick to minimize my code,
var pageName = getPageName();
var page = require('./' + pageName);
I get error Uncaught Error: Cannot find module './maps' in console log in Chrome. Why does it not work when I use string concatenation but works when I use pass the path explicitly?
That is a limitation of Browserify and similar type libraries. In order to do the require() the library has to examine the js code as a string, and determine file paths before the code is run. This means file paths have to be static in order for it to be picked up.
https://github.com/substack/node-browserify/issues/377
Browserify can only analyze static requires. It is not in the scope of
browserify to handle dynamic requires

Problem using Dojo build tool, 'could not load' error now occuring when trying to use compiled scripts

I was following along to this post by Rebecca Murphey: http://blog.rebeccamurphey.com/scaffolding-a-buildable-dojo-application
I was substituting her file structure with my own.
Running the normal version of the scripts works fine, but the moment I compile them using the build tool, the script errors.
It's very likely a small problem with how the files are referenced via my Profile.js script but maybe someone here can help me get the settings correct before running the build tool so the compiled files will work as they should.
My file structure is as follows...
/www
/Assets
/Scripts
/Classes
build.sh
Init.js
Load.js
Profile.js
/Dojo
Dojo.js
/dojo-sdk
index.html
My index.html file has the following code...
<script>
var djConfig = {
modulePaths : {
'Integralist' : '../Classes'
}
};
</script>
<script src="Assets/Scripts/Dojo/Dojo.js"></script>
<script>
dojo.require('Integralist.Init');
</script>
...and the Init.js file has the following code...
dojo.provide('Integralist.Init');
dojo.require('Integralist.Load');
dojo.declare('MyApp', null, {
constructor: function(config) {
this.version = config.version || '1.0';
this.author = config.author || 'Unknown';
}
});
var myapp = new MyApp({
author: 'Mark McDonnell'
});
alert(myapp.author);
alert(myapp.version);
...lastly, the Load.js file has nothing in it but this...
dojo.provide('Integralist.Load');
alert('I\'m the Load.js file');
...and this all runs fine. When I load index.html I get 3 alert messages, brilliant.
The problem occurs when I try to run the build tool.
Via Mac OSX i locate the /Classes/ directory and run 'sh build.sh' and the build.sh file within the /Classes/ directory consists of the following code...
cd ../../../dojo-sdk/util/buildscripts
./build.sh profileFile=../../../Assets/Scripts/Classes/Profile.js releaseDir=../../../Assets/Scripts/Release
...now, after running the build tool I have a new /Release/ directory created within my /Scripts/ directory, this /Release/ directory consists of...
/www
/Assets
/Scripts
/Release
/Integralist
/Classes
Init.js
Init.js.uncompressed.js
/dojo
--loads of dojo related files--
...I then created a separate index file called index-release-version.html and changed the script code as suggested by the article, so it looks like this...
<script src="Assets/Scripts/Release/Integralist/dojo/dojo.js"></script>
<script>
dojo.require('Integralist.Init');
</script>
...from here I get the following error...
Failed to load resource: the server responded with a status of 404 (Not Found)
Uncaught Error: Could not load 'Integralist.Init'; last tried '../Integralist/Init.js'
...and just for reference my Profile.js file that is used by the build tool consists of the following (and it's here I think the problem may be)...
dependencies = {
stripConsole : 'all',
action : 'clean,release',
optimize : 'shrinksafe',
releaseName : 'Integralist',
localeList : 'en-gb',
layers: [
{
name: "../Classes/Init.js",
resourceName : "Integralist.Init",
dependencies: [
"Integralist.Init"
]
}
],
prefixes: [
[ "Integralist", "../Classes" ]
]
}
Any help really appreciated as I desperately want to get my head around how Dojo works :-)
Thanks!
M.
I'd suggest working from the repo I linked to from my blog post (http://github.com/rmurphey/dojo-scaffold) -- I double-checked that it's definitely working :) -- and make changes to it until your changes break something, rather than trying to create your own structure right off the bat.
At a glance, I'm not 100% clear why you've got a Dojo.js file inside your directory structure, (is this the base Dojo lib or something else?), but the rest of Dojo is located elsewhere. If you use the structure I proposed, you can safely remove the djConfig declaration when using the built files, but as Dan mentioned, you may need to keep it if you're using a different configuration.
Do you have that djConfig variable in your index-release-version.html? It looks like Dojo is trying to find init.js at ../Integralist/Init.js, but you somehow need to tell it to look in ../Classes/Init.js
This is what your modulePaths : {'Integralist' : '../Classes'} was doing in your Index.html

Categories

Resources