I was working on a React Native Native Module for Android. And it is written in Java (as what I researched from official docs and the internet). The problem is, I need to use a Node.JS based module to implement the functions that I want. Is there any possibility to use Node.JS module in Java?
The Node.JS module currently using a few Node native libraries such as fs and path. The code is 100% written using Node.JS.
Or is there any other way to create a React Native module without the use of Java?
The ultimate goal is to use this Node.JS based module to React Native App (without create a bridge between Node and React Native).
As I understand your question, your module doesn't have to communicate with native side. If it's that what you need, it will so easy to achieve. I'll make a simple example:
yourModule.js
export function a() {
// do sth
}
export function b() {
// do sth
}
export function c() {
// do sth
}
yourComponent.js
There is 2 ways to use your module:
1.
import { a, b } from '/path/yourModule'; // if you want to import some of the functions
class yourComponent {
function test() {
a(); // call function a from module
}
}
// Remember to check function's name if it's duplicated with other modules
2.
import * as module1 from '/path/yourModule';
class yourComponent {
function test() {
module1.a(); // call function a from module
}
}
// In this case, you won't have to worry about duplicated function's name, but you still
// have to check duplicated of the name of modules you have imported. For this example,
// the name module1 has been used.
P/s: you might get some error when using export/import incorrectly. So please investigate more about React Native export/import.
Related
I have a class file, utility.js for all the common functions.
However some of the functions require certain library import
e.g: NetInfo library
utility.js
import NetInfo from "#react-native-community/netinfo";
export async function networkConnection() {
const state = await NetInfo.fetch();
return state.type;
}
However, in order for utility.js to be reusable in another project, another project has to have NetInfo installed. Is it a good practice if instead of importing modules directly, I import only when I need to use it, and pass the import object along to the function?
utility.js
export async function networkConnection({ NetInfo }) {
const state = await NetInfo.fetch();
return state.type;
}
and when using it
app.js
import NetInfo from "#react-native-community/netinfo";
import { networkConnection } from "./utility.js"
const network = networkConnection({ NetInfo })
This way, I can copy and paste utility.js to any project, without the need to install all the import packages. Also, this pattern seems to be able to resolve common Circular Dependencies error by limiting the import statement.
Is this the best practice for creating a common, reusable function file?
Your question illustrates the difference between a closure and a plain function, however, neither are pure.
If the function only serves to await a promise and return a property value, it doesn't really make sense to use the non-closure approach... unless you've created a module (utility.js in your example) with other exports unrelated to the NetInfo context. If that's the case, I think that's the issue to focus on: reorganization of your code's concerns.
How many characters it takes to get the value two ways:
console.log(`await networkConnection()`.length); // 25
console.log(`(await NetInfo.fetch()).type`.length); // 28
Is it worth the abstraction? Up to your brain and your fingers.
I have tried exporting some functions to the main.js file in scalajs using #JSExportTopLevel annotation, as explained in the Export Scala.js APIs to JavaScript scalajs documentation and building the main.js as explained here.
This results in main.js from which I am able to make use the functions exported in the scalajs code.
Now I want to use these exported functions in my reactjs components. For this I tried following steps:
Copy the main.js file in the public folder
Include the javascript file in the index.html, like so:
<script type="text/javascript" src="./main.js"></script>
Now, if I load the app in the browser and try to use these functions in the browser console, it works fine:
console.log(foo());
But I am not the utilise these functions in reactjs components:
import React from 'react';
const RuleEditor = () => {
console.log(foo());
return (
<>
</>
);
};
export default RuleEditor;
I always get the following compilation error:
foo is not defined no-undef
I do understand that reactjs is not able to recognise the function as I haven't really specified where to get that function from but I am not really sure how to achieve it. I have gone to couple of other stackoverflow posts where some suggestions where to look for it in window object but I didn't find those functions there.
Please suggest a proper way to make use of functions exported from scalajs in reactjs components. TIA.
Exporting objects/classes/functions as top level exports put them in Javascript global scope.
class Foo(val x: Int) {
#JSExport
def square(): Int = x*x // note the (), omitting them has a different behavior
#JSExport("foobar")
def add(y: Int): Int = x+y
}
You can utilise these functions in the scripts embedded in html or in scalajs as shown here.
But if you need to use these functions in a nodejs app, you need to export these functions from a module. We need to add the following in the build.sbt. Read more here.
scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.ESModule) }
Now, we can make use of the exported functions in a nodejs app by importing them like so:
import { square, add } from './main'
If you wish to export these functions from a module named other than main, provide module id for each exported function like so:
class Foo(val x: Int) {
#JSExport("square", "my-math")
def square(): Int = x*x // note the (), omitting them has a different behavior
#JSExport("foobar", "my-math")
def add(y: Int): Int = x+y
}
and use it like so:
import { square, add } from './my-math'
I am from a C++ background and have a day's experience in TypeScript. I am trying to implement a design (interface/class) that is split between multiple files. It is flashing runtime error : 0x800a1391 - JavaScript runtime error: 'module' is not defined
Info.ts
export = Test; <----------- 0x800a1391 - JavaScript runtime error: 'module' is not defined
namespace Test {
export class Info {
}
}
TestWrapper.ts
import { Info } from "./Info";
namespace Test {
class TestWrapper {
public GetInfo(): Info {
return this.m_info;
}
}
}
Am I using something in the wrong way?
A guess:
export = Something
Compiles to something like
module.exports = Something
module.exports is a construct of the so-called "commonjs module system", something that is not available in browsers, but in node.js. So if you run the generated code in a browser through a direct <script> import, it will bring an error like that. TS transpiles imports and exports to module systems that can be specified in the tsconfig.json, but TS itself is not responsible for implementing the module system.
What to do?
If this code is really supposed to run in the browser, you could opt on one of the 2 following options:
Run the code through a module bundler (webpack), which will generate a browser compatible "bundle" (a big JS) concatenating all your files. Webpack has ways of including typescript as a plugin, so that you dont need to make your "build" a 2-step process; Module bundlers are usually fairly complicated.
Make your files module-less (which means: no top-levem imports or exports) and import them through vanilla <script> tags.
Am I using something in the wrong way?
While namespaces are commonly used in other languages, they do not exist in JavaScript, so the typescript version is just some rarely used way to add proper typing to some things (I never used it yet). In your case you actually don't need a namespace. Just:
export default class Info { /*...*/ }
Then you can
import Info from ".Info";
export default class TestWrapper { /*...*/ }
PS: That said, I actually don't know how to make this work with namespaces to resolve the error
It looks like you are trying to mix modules and namespaces. I would suggest reading Namespaces and Modules.
You don't need to to export at the top level using export = Test, you also shouldn't import { Info } from "./Info"; because Info is part of the Test namespace which TestWrapper is a member of.
If you want to go the namespace route, consider:
Info.ts
namespace Test {
export class Info {}
}
TestWrapper.ts
namespace Test {
export class TestWrapper {
m_info: Info;
public GetInfo(): Info {
return this.m_info;
}
}
}
Consumer.ts
console.log(Test.TestWrapper);
Compile this using:
tsc --outFile foo.js Info.ts TestWrapper.ts Consumer.ts
Then run using:
node foo.js
Which prints:
[Function: TestWrapper]
There is a well-known approach in node.js to leverage the module factory pattern. For, example:
m.js
function factoryMethod(module) {
// doing some stuff and returning object initialized with module parameter
}
app.js
var o = require('./m')(module);
// using o
How can I do the same in typescript. Actually, creating m.ts is not a problem:
m.ts
function factoryMethod(module: NodeModule): any {
// doing some stuff
}
export = factoryMethod;
But how should I use import syntax to use this module factory method like in javascript?
I'm not sure I quite get this common pattern. You're passing the module object from one module into another? All kinds of other objects are passed around like this, (e.g. app, db), but I don't like the idea of passing around the module object. I'd be tempted to call it an anti-pattern. Surely the module object should stay in the module to which it belongs.
That said, if you just want to import and call a function on the same line, you could do this using Node's require() function, just like regular JavaScript. Let's say you are passing an Express app rather than module.
const o = require('./m')(app);
However, you lose type-safety with this; o will be of type any. You would have to explicitly define the type of o.
const o: Module = require('./m')(app);
This is a bit silly. In fact, Module is likely to be defined in the module you are requiring anyway, so it is likely also self-defeating. My suggestion is this. Don't expect to use the same patterns you are used to in plain JS in TypeScript, which has its own patterns.
One thing you could do is import the function at the top, and then call it later. TypeScript uses ES2015-style modules, which don't allow you to import a function and call it on the same line. You will have to rewrite both files, since export = is not valid in ES2015.
// m.ts
interface Module {
// properties, methods, etc.
}
export function factoryMethod(app: Express.Application): Module {
let module = {};
// Initialize module methods, properties, etc.
return module;
}
The interface allow type inference in app.ts, which is an improvement of a kind.
// app.ts
import {factoryMethod} from './m';
// ...
let o = factoryMethod(app);
But this is still very silly. We don't need to define an interface and all that nonsense. Instead, we can use a class. Classes are very often the answer in TypeScript, and you'll find that most patterns in TypeScript involve them.
// m.ts
export class Module {
constructor(private app: Express.Application) { }
cache: string[];
someMethod(): Promise<Express.Response> {
// do something with this.app
}
}
And then in app.ts
import {Module} from './m';
// ...
let o = new Module(app);
Now we don't have to worry about interfaces and all that. The class itself is a type. This is quite a bit different from what you are likely to see in a typical Node app, but it is the sort of pattern you find all the time in TypeScript.
Hopefully that gives you some ideas.
import {factoryMethod} from './m.ts'
let module = factpryMethod('module');
I know this question is fairly old but I came across the same issue when converting an existing JS project to TypeScript that makes use of this pattern.
Instead of having to pre-define the module definition in an interface we can use the ReturnType helper to get a type definition of the return type of a function!
This is what the module might look like:
function initModule(arg1: number, arg2: number) {
function functionA() {
return arg1;
}
function functionB() {
return arg2;
}
return {
functionA,
functionB,
};
}
export default initModule;
export type SampleModule = ReturnType<typeof initFactory>;
And here is how we could use it:
import initModule, { SampleModule } from './factory';
const newModule: SampleModule = initModule(1, 2);
newModule.functionA(); // 1
newModule.functionB(); // 2
Seriously, how cool is TypeScript? :)
I have recently discovered Meteor and I am struggling with using ES6 classes and imports in a new Meteor project. What I want to do is to have a complex structure of classes, which methods get called from Meteor events/methods/helpers. I've added Babel.js to the project by writing a command $ meteor add grigio:babel and it works properly.
Example of what I am trying to achieve:
in server/models/article.js:
class Article {
static all() {
//returns all articles from db
}
}
in server/methods/articles.js:
Meteor.methods({
allArticles: {
Article.all();
}
})
Having just that raises ReferenceError: Article is not defined in a methods file, which is adequate. So I have got three options: write all classes in one file, append all classes to a global object or use a good module system like Browserify. Obviously, third option is better.
But how do I use that? Babel converts export, import into Browserify by default and Meteor raises a require is not defined error on page refresh. After googling the problem I didn't find a clear solution on how to add Browserify to Meteor. Should I add a npm packages support to Meteor, add a npm package of browserify and add it manually to Meteor on every page where I import/export anything? Or should I use a completely different approach? How is this task usually handled in Meteor? Thank you!
I was reading about this earlier and found this issue on github that may help.
Essentially just assign the class to a variable that is exposed to both the client and server (lib/both/etc depends on your file structure). Like so:
Article = class Article {...}
Seems to be the best solution at the moment.
The way I do this is to collect objects together into various namespaces, for example:
// Global
Collections = {};
class Article {
static all() {
//returns all articles from db
}
}
_.extend(Collections, { Article });
Then to avoid having to use Collections.Article everywhere I can use the following in the file I need to access Article in:
// Make `Article` available
let { Article } = Collections;
I am using Meteor 1.4.1.1 and the error remains, when reproducing your approach. However, there are some new ways to use es6 classes now:
1. Export your class as a constant (e.g. for use as a singleton object):
class MyModuleInternalClassName {
//... class internals
}
export const PublicClassName = new MyModuleInternalClassName();
You can import this one via
import {PublicClassName} from 'path/to/PublicClassFileName.js';
2. Export your class directly as the module's default
export default class PublicClassName {
//... class internals
}
and then import it (as with the above one) as the following
import {PublicClassName} from from 'path/to/PublicClassFileName.js';
let myInstance = new PublicClassName();
+++++++++++++++++++++++++++++++++
Regarding the question of OP and the error, you can try something like this:
Article.js
class InternalArticle {
constructor(){
//setup class
}
all() {
//returns all articles from db
}
register(article){
//add article to db
}
}
export const Article = new InternalArticle();
Import and use the Singleton
import {Article} from 'path/to/Article.js';
//either register some article
Article.register(someArticle);
//or get all your articles
const allArticles = Article.all();