Using command line arguments with ReactJS - node.js

I'm wondering if it's possible to use command line arguments with ReactJS (not react-native). For example, is it possible to input a simple string and have it be saved as a variable so it can be displayed? The npm yargs module is the kind of thing I'm looking for, but I couldn't get that to work because the child process it spawns apparently doesn't work in a browser.
Edit: I've also tried something like including {process.argv[0]} in say an h1 tag, but nothing shows up.

React doesn't have anything special for command line arguments. In fact, it is primarily designed as a DOM library. You could use yargs and then pass the values to a React component.

For example you run this command in terminal or cmd
npm start -- foo
foo is your argument.
You can print your like this
// print process.argv
process.argv.forEach(function (val, index, array) {
console.log(index + ': ' + val);
});
in your script.

React runs is client-side
React is a client-side library. It runs in a web page, on a browser. The end-user doesn't use the command-line to "run" React, therefore command-line arguments are not available to the end-user.
For developers
As a developer, you do use tools to start a development server and launch a browser that is running React. Most likely, you're using Create React App. You can use environment variables to pass variables/arguments to React. Specifically, the documentation offers these examples:
# on Linux and macOS
REACT_APP_NOT_SECRET_CODE=abcdef npm start
# on Windows (cmd.exe)
set "REACT_APP_NOT_SECRET_CODE=abcdef" && npm start
Note that these variables are embedded into React at build time, when Create React App bundles and builds your app (kind of like compiling). This means that if you build your React project and then transfer the output files to another server and try to pass new variables, nothing will change.
For servers
If your React build files are on a server and you want to be able to pass command-line arguments to the server and have React change, this is also possible, but largely depends on what software you are using to serve. Broadly, the server would take the runtime argument and pass it into the template which renders your React app. Then any Javascript that runs on that page can access the arguments.

Related

Invalid Hook Call error when running Next app from PM2

We have an install of Node.js running on a Windows Server 2012R2 web server. A developer created an application for us using Next/React/Node (I'm not a web developer so I'm unsure of the specifics of the various development tools used). This app works fine when manually started on the command line like this:
C:\NodeApps\pacifield>"C:\PROGRAM FILES\NODEJS\NODE.EXE" C:\NodeApps\pacifield\node_modules\next\dist\bin\next start
However this requires someone to manually login and restart the app whenever the server is rebooted or the app stops for whatever reason. I am trying to setup PM2 to run the app. I have it up and running fine until you browse to the app - at which point you get the following error:
next-server.ts:306 Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
at resolveDispatcher (c:\NodeApps\pacifield\node_modules\react\cjs\react.development.js:1476:13)
at useContext (c:\NodeApps\pacifield\node_modules\react\cjs\react.development.js:1484:20)
at useSession (c:\NodeApps\pacifield\node_modules\next-auth\dist\client\index.js:75:39)
at Provider (c:\NodeApps\pacifield\node_modules\next-auth\dist\client\index.js:588:12)
at processChild (C:\NodeApps\pacifield\node_modules\react-dom\cjs\react-dom-server.node.development.js:3353:14)
at resolve (C:\NodeApps\pacifield\node_modules\react-dom\cjs\react-dom-server.node.development.js:3270:5)
at ReactDOMServerRenderer.render (C:\NodeApps\pacifield\node_modules\react-dom\cjs\react-dom-server.node.development.js:3753:22)
at ReactDOMServerRenderer.read (C:\NodeApps\pacifield\node_modules\react-dom\cjs\react-dom-server.node.development.js:3690:29)
at Object.renderToString (C:\NodeApps\pacifield\node_modules\react-dom\cjs\react-dom-server.node.development.js:4298:27)
at Object.renderPage (C:\NodeApps\pacifield\node_modules\next\dist\server\render.js:596:45)
I have checked and there is only the one installation of React in C:\NodeApps\pacifield\node_modules\react and the other suggestions don't seem to make sense when it runs fine outside of PM2. I have checked with ProcessExplorer that all the environment variables are the same (except for the additional ones PM2 adds) when the app is run from the command line vs. PM2.
Anyone have any suggestions?
Hooks can only be call inside of functional component or inside another hook.
take note: Invalid Hook Call Warning
Notify your frontend developer it.

React Native - Clear Async Storage Script

I'm currently building a react native app which uses async storage. I've got conditionals within the components to decide whether to make requests to the API or use the data stored in memory. So to test out these conditionals I regularly have to clear the AsyncStorage using AsyncStorage.clear().
This works if I have it in one of the components, however it would be more practical to have it in a seperate script - which brings me to my question:
I want to have a script as below:
import AsyncStorage from '#react-native-community/async-storage';
AsyncStorage.clear();
console.log('STORAGE CLEARED');
and then run it using a command like node clearStorage.js (and later an npm script).
However I'm getting an error saying 'Cannot use import statement outside a module'.
Am I missing anything glaringly obvious/trying to do something I shouldn't? I've tried changing the file type to .mjs with no luck.
If you need to do this, you can't use a nodejs script because the node script will never get to the native side, because async-storage is a native library and it connects directly to Android or IOS.
Another solution may be at the start of the application, you can run that code, or create a Button just for dev mode and when click clean the data.
and the error 'Cannot use import statement outside a module'. it's because nodeJs don't understand the syntax import AsyncStorage from '#react-native-community/async-storage'; they need a transpiler like babel.

Sails.js: can't find variable require (react-bootstrap-datetimepicker)

I'm using Sails js and I want to use a nodejs module.
I also use React js.
I want to use react-bootstrap-datetimepicker in my javascript script.
react-bootstrap-datetimepicker
I installed my module with npm install react-bootstrap-datetimepicker
I tried in config/boostrap.js to add this line var DateTimeField = require('react-bootstrap-datetimepicker');, but DateTimeField isn't recognised in my js script.
Uncaught ReferenceError: DateTimeField is not defined
I also tried to add this line directly in my script, but I have this error:
ReferenceError: Can't find variable: require
And also this one in my script: import DateTimeField from "react-bootstrap-datetimepicker";
I have all these errors in the navigator console.
EDIT 1:
I understand what you said, thank you for your answer.
BUT, for example with react-bootstrap, I can use:
var Input = ReactBootstrap.Input;
var ButtonInput = ReactBootstrap.ButtonInput;
There is exactly the same architecture with react-bootstrap-datetimepicker, so I maybe I can do the same?
var DateTimePicker = ... . DateTimePicker
I tried to include like you said, but it doesn't recognise DateTimePicker.
Here is the doc:
Installation :
npm install react-bootstrap-datetimepicker
Then
javascript
var DateTimeField = require('react-bootstrap-datetimepicker');
render: function() {
return <DateTimeField />;
}
See (examples/) for more details.
And in examples/, the line is:
import DateTimeField from "react-bootstrap-datetimepicker";
Ok, first you have to understand the division of server side and client side javascript, even thought you are using the same language, and you can share libraries, bare in mind, that for client side js you need to supply the user browser with the libraries and scripts it needs, so those have to be in the html you serve the user. When you require any module in sails bootstrap or similar, you are loading the script into the server memory, not serving it to the users browser, that means you can use in the server code, but not in client code.
For you use case, you have to download the library code, and put it in your assets/js folder and if you have the script tags in the layout, sails will automatically inject it there for you, but if not or you are using other template engine like jade, just manually add it.
example:
<html>
....
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/<react-version>/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/<react-version>/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-bootstrap/<version>/react-bootstrap.min.js">
<script src='/js/react-bootstrap-datetimepicker.min.js'></script>
// The other js files that depend on datetimepicker go here
</html>
Now just to be clear, require is a node.js function, node.js is not the same as javascript, its a piece of software with its own functions, thats why you are getting an error related to it when trying to use it in the browser, there is no require method there, so you can't use it, at least not directly. You can use browserify to sort of emulate the node workflow, where you have a node_modules folder and use require on those, browserify will bundle (search for the modules and merge them) and give you a javascript file that you can then link in your html code. That is more setup work, and unless you really need it, because you have a lot of files, i think is not worth the effort.. lets say for just one file using require.
So i think you were misguided by that github repo, because it says npm-install. Just ignore it (unless you use browsefify like i said) and download the link i gave you above ( the .min.js).
So to sumarize, you issue have nothing to do with sails, just link the library in the html you provide to the user, like any other client side script.

Shim config not supported in Node, may or may not work

I am working on a project which works fine on browser , now we are trying to run it on server side using nodejs.
I have below configurations :
node : v4.2.1
npm : v2.14.7
and when I am trying to run my project on nodejs , getting the error as :
Shim config not supported in Node, may or may not work
Since the modules and dependencies (AMD) are working fine on browser I assume the shims config are correct .
Please let me know if I am missing something ?
https://github.com/jrburke/requirejs/issues/1443
Regards
Manish
Since the modules and dependencies (AMD) are working fine on browser I assume the shims config are correct .
That's an incorrect assumption. The problem is that Node.js operates with a set of basic assumptions that are very different from how browsers work. Consider this statement:
var foo = "something";
If you execute this at the top of your scope in Node.js, you've created a variable which is local to the file Node is executing. If you really want to make it global, then you have to explicitly shove it into global.
Now, put the same statement at the top of the scope of a script you load in a browser with the script element. The same statement creates a global variable. (The variable is global whether or not var is present.)
RequireJS' shim configuration is used for scripts that expect the second behavior. They expect a) that anything they declare at the top of their scope is leaked to the global space and b) that anything that has been leaked to the global space by scripts they depend on is available in the global space. Both expectations are almost always false in Node. (It would not be impossible for a module designed for node to manipulate global but that's very rare.)
The author of RequireJS explained in this issue report that he does not see it advisable for RequireJS to try to replicate the browser behavior in Node. I agree with him. If you want to run front-end code in the back-end you should replace those modules that need shim in the browser with modules that are designed to run in Node.

Meteor.js: How do you require or link one javascript file in another on the client and the server?

1) In node on the backend to link one javascript file to another we use the require statement and module.exports.
This allows us to create modules of code and link them together.
How do the same thing in Meteor?
2) On the front end, in Meteor is I want to access a code from another front end javascript file, I have to use globals. Is there a better way to do this, so I can require one javascript file in another file? I think something like browserify does this but I am not sure how to integrate this with Meteor.
Basically if on the client I have one file
browserifyTest.coffee
test = () ->
alert 'Hello'
I want to be able to access this test function in another file
test.coffee
Template.profileEdit.rendered = ->
$ ->
setPaddingIfMenuOpen()
test()
How can I do this in Meteor without using globals?
Meteor wraps all the code in a module (function(){...your code...})() for every file we create. If you want to export something out of your js file (module), make it a global. i.e don't use var with the variable name you want to export and it'll be accessible in all files which get included after this module. Keep in mind the order in which meteor includes js files http://docs.meteor.com/#structuringyourapp
I don't think you can do this without using globals. Meteor wraps code in js files in SEF (self executing function) expressions, and exports api is available for packages only. What problem do you exactly have with globals? I've worked with fairly large Meteor projects and while using a global object to keep my global helpers namespaces, I never had any issues with this approach of accessing functions/data from one file in other files.
You can use a local package, which is just like a normal Meteor package but used only in your app.
If the package proves to be useful in other apps, you may even publish it on atmosphere.
I suggest you read the WIP section "Writing Packages" of the Meteor docs, but expect breaking changes in coming weeks as Meteor 0.9 will include the final Package API, which is going to be slightly different.
http://docs.meteor.com/#writingpackages
Basically, you need to create a package directory (my-package) and put it under /packages.
Then you need a package description file which needs to be named package.js at the root of your package.
/packages/my-package/package.js
Package.describe({
summary:"Provides test"
});
Package.on_use(function(api){
api.use(["underscore","jquery"],"client");
api.add_files("client/lib/test.js","client");
// api.export is what you've been looking for all along !
api.export("Test","client");
});
Usually I try to mimic the Meteor application structure in my package so that's why I'd put test.js under my-package/client/lib/test.js : it's a utility function residing in the client.
/packages/my-package/client/lib/test.js
Test={
test:function(){
alert("Hello !");
}
};
Another package convention is to declare a package-global object containing everything public and then exporting this single object so the app can access it.
The variables you export NEED to be package-global so don't forget to remove the var keyword when declaring them : package scope is just like regular meteor app scope.
Last but not least, don't forget to meteor add your package :
meteor add my-package
And you will be able to use Test.test in the client without polluting the global namespace.
EDIT due to second question posted in the comments.
Suppose now you want to use NPM modules in your package.
I'll use momentjs as an example because it's simple yet interesting enough.
First you need to call Npm.depends in package.js, we'll depend on the latest version of momentjs :
/packages/my-moment-package/package.js
Package.describe({
summary:"Yet another moment packaged for Meteor"
});
Npm.depends({
"moment":"2.7.0"
});
Package.on_use(function(api){
api.add_files("server/lib/moment.js");
api.export("moment","server");
});
Then you can use Npm.require in your server side code just like this :
/packages/my-moment-package/server/moment.js
moment=Npm.require("moment");
A real moment package would also export moment in the client by loading the client side version of momentjs.
You can use the atmosphere npm package http://atmospherejs.com/package/npm which lets you use directly NPM packages in your server code without the need of wrapping them in a Meteor package first.
Of course if a specific NPM package has been converted to Meteor and is well supported on atmosphere you should use it.

Resources