Export NativeModules for NPM in React-Native - javascript

I'm trying to create a node module from my React Native App. The problem is, that the module is mostly a NativeModule. So my index.js looks like this:
import { NativeModules } from 'react-native';
export default NativeModules.MyNativeClass;
When i install my package to my node_modules (inserted local relative path to package.json) and import it to my JS file, it's always undefined.
I tried to export a test object, like export default {test:'test'}; and it works. So, is it possible to export the Native Module through node_modules?

If anyone is stuck to the same issue. Just link it with
react-native link
and your native modules from your node_modules get visible.

Related

why my react native become .tsx instead .js

so after installing react native using npx react-native init MyProject the project is running and open in emulator but the app file is not app.js instead app.tsx,
file strcuture
The question is i am new to react native and many tutorial i see is havgin App.js file, and the code in app.js is different between js and tsx at least that's what i see, or is it just the same if i follow tutorial like folder structure, syntax and everything.
That's because of this
New projects created by the React Native CLI or popular templates like Ignite will use TypeScript by default.
Read Using JavaScript Instead of TypeScript
You can just rename your tsx to jsx
Well, I had the same concerrns earlier today while working on the current version 0.71. This version does not create a App.js file. What I did was- I created a file App.jsx and added this code:
import { StyleSheet, Text, View } from 'react-native'
import React from 'react'
const hello = () => {
return (
<View>
<Text>App</Text>
</View>
)
}
export default hello
const styles = StyleSheet.create({})
it automatically renders the code in it instead of the default App.tsx file
You can write your JavaScript code in the Ap.jsx file

How to use i18next as a peer dependency for my component library?

I am building a React component library which contains some translations, but I want these translations to be provided by the user of my package.
The reason for this is that these translations should be customizable, and I don't want to include every possible language in this package.
So what I'd like to achieve is to use useTranslations inside my component library like this:
import React from 'react';
import { useTranslation } from 'react-i18next';
const MyComponent = () => {
const { t } = useTranslation();
return <div>{t('helloWorld')}</div>;
};
And somehow the 'helloWorld' translations should be configurable by the user of the library.
Is there any way to achieve this?
Apparently this was caused by yarn link using two versions of react-i18next.
To solve this I've configured my app to use the react-i18next version of my package:
cd my-package/node_modules/react-i18next
yarn link
cd my-app
yarn link react-i18next
Now my package uses the i18next instance configured in my app.

Javascript ES6 modules name resolution

I'm absolutely sure, that I'm asking a silly question, but I really do not understand how this line of code works
import React from 'react';
My question: who and where searches for 'react' name?
For example, this site tells me, that for module-name I should use relative of absolute path, e.g
import React from './react';
or
import React from '/home/user/react';
I thought that 'react' is same as './react' but I've created ReactJS applcation via create-react-app command and didn't find any file named react.js in application folder.
So, obviously there is some tool or rule by which module name has been resolved to a proper file, but I cannot find proper documentation about this.
Import statements are importing packages by name from the node_modules directory in your app, which is where they're saved when you run an installation command such as npm install or yarn inside your app.
When you write:
import React from 'react';
As far as you're concerned, it's as if you'd written:
import React from './node_modules/react/index.js';
Importing by package name means you don't have to be aware of how a given package is structured or where your node_modules directory is relative to your javascript file.

Cant import Vue library from Javascript file

I have exported a Vue component library targeted as a library. But trying to import it does not work. I get the error Cannot read property extend of undefined.
It happens on the line where it tries to export Vuetify colorable. So one way to fix this may be exporting it without Vuetify and somehow use it as a dependency instead.
I CANNOT export it as an npm module so do not suggest that.
My build script:
"build-bundle": "vue-cli-service build --target lib --name test-component-library src/index2.js",
My index2.js:
import TestComponent from './components/TestComponent/TestComponent' // Expansionheader
const FirstLibrary = {
install (Vue) {
Vue.component('test-component', TestComponent);
}
};
// Automatic installation if Vue has been added to the global scope.
if (typeof window !== 'undefined' && window.Vue) {
window.Vue.use(FirstLibrary)
}
export default FirstLibrary;
Import is in index.html like:
<script src="test-component-library.umd.js"></script>
I tried both using the common and the umd build files. Both of them give errors. Can anyone help me resolve this? Or know a way to export the library without Vuetify?
Thank you in advance

Import from subfolder of npm package

I've been working on creating a small library of React components for use in several other projects. I am publishing the package internally (using a private GitHub repository) and then including in another project. However, when I go to import from a subdirectory of the package I am not able to do so as the paths don't match.
The projects using the package all utilize webpack to bundle/transpile code as I am trying to avoid doing any building in the component library if possible.
Directory Structure
- package.json
- src/
- index.js
- Button/
- index.js
- Button.jsx
- ButtonGroup.jsx
- Header/
- index.js
- Header.jsx (default export)
package.json
...
"main": "./src/index.js",
"scripts": "",
...
src/Button/index.js
import Button from './Button';
import ButtonGroup from './ButtonGroup';
export default Button;
export { Button, ButtonGroup};
src/index.js
Is this file actually necessary if only importing from subdirectories?
import Button from './Button';
import ButtonGroup from './Button/ButtonGroup';
import Header from './Header';
export { Button, ButtonGroup, Header };
Other Project
// This project is responsible for building/transpiling after importing
import { Button, ButtonGroup } from 'components-library/Button';
Example
Material-UI is a library of React components that is used by requiring in the following fashion: import { RadioButtonGroup } from 'material-ui/RadioButton. I've tried to figure out how this works for them but to no avail yet.
Similar Questions
How would I import a module within an npm package subfolder with webpack?
This is very nearly the correct approach I require, except that the import path used there involved the src/ directory, which I am trying to avoid (should be component-library/item, not component-library/src/item (which does work currently though))
Publishing Flat NPM Packages
This is exactly what I want except that I was hoping to not have a "build" phase in the package (rely on importing locations to build/transpile)
Questions
Can I skip the src/ directory somehow in the import path?
Can I skip any type of build phase in the package (so developers don't have to build before committing)?
How does a package similar to material-ui handle this?
Can I skip the src/ directory somehow in the import path?
Yes. Using the package.json "exports" field, which should be supported by Webpack in a near future (see this issue), but has already been supported by Node since Node 12 LTS following the Bare Module Specifier Resolution proposal:
package.json
...
"main": "./src/index.js",
"type": "module",
...
"exports": {
"./Button": "./src/Button/index.js",
"./Header": "./src/Header/index.js"
},
...
Now, the following code:
// This project is responsible for building/transpiling after importing
import { Button, ButtonGroup } from 'components-library/Button';
should be translated to:
import { Button, ButtonGroup } from 'components-library/src/Button/index.js';
which should correctly import the requested modules.
Caveat
Now, it would certainly be tempting to try a simpler version like:
...
"exports": {
"./Button": "./src/Button/",
"./Header": "./src/Header/"
},
...
so as the usual import statement
import { ... } from 'components-library/Button';
gets translated to
import { ... } from 'components-library/src/Button';
This looks nice, but it will not work in this case, because your submodules don't have each their own package.json file but rely on their index.js file to be found.
/!\ Unlike in CommonJS, there is no automatic searching for index.js or index.mjs or for file extensions.
src/index.js - Is this file actually necessary if only importing from subdirectories?
I don't think so, but you can keep it if you want.
Can I skip any type of build phase in the package?
Using the "exports" field does not require you to transpile your code.
The answer may depend on how you installed your components library. If you did it via either npm install <git-host>:<git-user>/<repo-name> or npm install <git repo url>,
You should be able to import {Button} from 'component-library/Button' as is, according to your first linked question. Similar to Node's require() resolution, Webpack should resolve subdirectories within component-library relative to component-library's entry point. You can find the docs on customizing the resolution behavior via the webpack.config.resolve property. material-ui seems to rely on resolving subdirectory imports from the module entry directory.
To distribute an ES module library, there's no need for building before distribution. However, projects such as create-react-app may need a pre-transpiled version.
Alternately, you can write import {Button} from 'components-library'.
Webpack will trace the dependencies back through each index without a fuss.
you have to install babel-plugin-module-resolver package
Specify the package relative path in your .babelrc file alias like this
{
"plugins": [
["module-resolver", {
"alias": {
"components-library": "./node_module/components-library"
}
}]
]
}
then you can import subdir of npm package like this
import { Button, ButtonGroup } from 'components-library/Button';
One of the possible solutions there is webpack aliasing system.
You can create another project, call it for example 'app-aliases', so your aliases will be reusable.
This project will has one js file with all of your packages paths:
const path = require('path');
module.exports = {
'#components': path.resolve(__dirname, 'node_modules/components-library/src'),
'#another': path.resolve(__dirname, 'node_modules/any/path/you/want'),
}
And then add it to the webpack configuration in any project which will be responsible for building/transpiling:
webpack.config.js
const appAliases = require('app-aliases');
const config = {
...
resolve: {
alias: {
...appAlises
}
}
}
In the runtime code you will be able to use it like this:
import {Button} from '#components/Button';
import {Something} from '#another'
If you are using typescript you will need to add the same aliases to the paths tsconfig property.
So answers to your questions are:
Yes, you can use any path in aliases
Yes, it is not necessary to build all of your projects
I see that now mui uses imports from directi packages (core for example), see https://material-ui.com/components/radio-buttons/ there is import Radio from '#material-ui/core/Radio';. But I hope they using re-export that I described below.
Also about node.js resolution mechanism.
When you import some library it tries to find node_modules/some-library/package.json and then main property inside it. This property should lead to your main entry point. Usually it is src/index.js (you should set it in package.json if it is no there yet). In this file you can re-export anything you want from internals file structure and will be able to use it without the full path.
Please see this repo for some examples.
I'am an angular developer never used react but what I could tell that material-ui are using monorepo where same concept exists in angular where we create one workspace and this workspace hold multiple project/packages as named in react. for more info Workspaces with Yarn
Material-ui using fake paths in tsconfig to make it appears like src folder doesn't exists this from the git you provided: tsconfig.json
This is possible but requires publishing a curated dist folder rather then the root of your project.
The whole thing is rather simple if you understand how module resolution works, and you just need a small script to prepare your distribution.
Lest I repeat all the details here, please see my answer for Importing from subfolders for a javascript package.

Categories

Resources