How to migrate from React Native app to a react-native module - javascript

I've created a react native app with react-navigation (is just a react-native code won't needed to develop in a specific platform) is a very short app with 3 screens to list info from an API.
This is working as registered application.
Now what I want to do is use my app as an imported component to be integrated from another react-native app ().
--------------------------------------------------------------------------------------
# AnotherApp.js
import React from 'react';
import { MyModuleFlow } from 'my-module-flow';
const AnotherApp = () => {
return (
<MyModuleFlow
param1={someValue}
onSuccess={data=> {
console.log('success', data);
}}
/>
);
};
export default AnotherApp;
-----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
# index.js
import { AppRegistry } from 'react-native';
import AnotherApp from './AnotherApp.js'
import { name as appName } from './app.json';
AppRegistry.registerComponent(appName, () => AnotherApp);
-------------------------------------------------------------------------------------
What should I do to migrate my project? my app has now some linked dependencies, I don't have any idea what to do.

You should create an npm module and publish it. It will bundle all your files and will push it to npm. Then you can import your modules anywhere.
This is what i follow: https://medium.com/#KPS250/publishing-react-native-modules-to-npm-40d2c4878a8e

Well, I found the solution by myself looking at bob library from the community
What I had to do was setup the project as js-module to be build,
native folders as ios and android wouldn't be needed anymore, so I removed those
bob init (following the interactive cli)
move all dependencies to devDependencies, and set
"peerDependencies": {
"react": "*",
"react-native": "*"
}
if you are using tsx like me, then run tsc --noEmit and fix all the warnings
yarn (will exec bob build, force it otherwise)
next steps, add an example folder -> all the info to do that is here.
if you have doubts use this repos as guide: react-native-tab-view react-native-paper
finally the bob build gave me the module wanted with the size I've expected 100kb and that's it
There is a special module to handle release (publish to npm, change the package version, tag branches, etc) release-it.
Hope that someone find this useful

Related

struggling for ract-native/react npm package + storybook

Hi i struggling to create a npm package, like so:
Phase 1:
a npm package that hosts react components and react-native components.
it will have storybook so to display either the react components and the react-native components
Phase 2: (this phase is not the problem, just post it for reference)
a desktop app that consumes the react components from the npm package
an expo application that consumes the react-native components from the npm package
At first the npm package can have just 2 simple components will do one for react and one for react-native, like so:
/desktop-components/Button.tsx
import React from 'react';
export const Button = () => <button>click</button>
mobile-components/Views.tsx
import { View } from 'react-native';
export const Views = () => (
<View><Text>Hello world</Text></View>
)
What i have tried so far:
created a library like so: npx create-react-native-library#latest react-native-awesome-module.
But in the doc here: https://reactnative.dev/docs/native-modules-setup the next steps are to create IOS module or android module and it becomes complex.
So, is it possible to just create 2 differenct components into the package and import them into expo and in the react app ? or should i go with the tutorial and start writing in java ?
are there any other examples of a npm package that hosts react components and react-native components, that i can install storybook in it ?
i hope my query is not so complex.

Share React-Native components

I am newbie in react, react-native and nodejs.
I tried create node module via npm init. In this module i created a component - for start styled button. I packed this via npm pack a link in application in package.json file by "file:../shared/_dist/shared-1.0.0.tgz" in dependency section.
in my shared index.js is
import MyButtonFirst from './components/buttons/MyButtonFirst';
module.exports = { MyButtonFirst };
in react application is
import React from 'react;
import { MyButtonFirst } from 'shared';
export default function MySharedButton()
{
return <MyButtonFirst />;
}
It works!
Then i tried create component which using react-native-async-storage/async-storage (via npm install in shared project). After increase version, npm pack, link and install new version of package I get error that AsyncStorage is null after android run.
Why AsyncStorage is null? Have I create dependecy in both projects? (that's a weird solution - it doesn't feel right to me, although it works)
How to share for example resources like icons, images etc.
We need to develop three applications on the same data (API) in the field of sports for different types of users (athlete, referee, administrator of the sports ground) and a lot of code we need to share - icons, contexts (user, theme etc...), error handling, API calls etc... We don't want develop it as one big rights-controlled application, but as several small applications for individual roles.
What is the best way how to share code between more react-native apps?
AsyncStorage is deprecated, see here.
You could create a start.js that links to different apps based on the feedback of your database (the roles of your users).
Else, it will route to a welcome component with, for example, a login and registration child-component.
import ReactDOM from "react-dom";
import Welcome from "./welcome";
import AppAth from "./app-ath";
import AppRef from "./app-ref";
import AppAdmin from "./app-admin";
fetch("api/users/role.json")
.then((res) => res.json)
.then((user_role) => {
if (user_role == "ath") {
ReactDOM.render(<AppAth />, document.getElementById("root"));
} else if (user_role == "ref") {
ReactDOM.render(<AppRef />, document.getElementById("root"));
} else if (user_role == "admin") {
ReactDOM.render(<AppAdmin />, document.getElementById("root"));
} else {
ReactDOM.render(<Welcome />, document.getElementById("root"));
}
})
.catch((err) => console.log(err));
Like that, you can keep the standard folder tree of an application in React and share all child-components, hooks and files in the public folder between them:
To keep the users separate, you store the role of the user in a cookie and check for the role on the server side.
If the cookie is empty, it will always lead back to the welcome component.
Side note: of course, the folder structure is always dependent on the bundler setup! So the folder structure of your app could differ from the one on the image.

Is there a way to integrate stencil components into frameworks locally without publishing to NPM?

I am currently testing stencil js. For now I want to write stencil components and include them within a VUE/React project. The official website of stencil already shows how to integrate them within a framework (https://stenciljs.com/docs/overview). But they assume that your own stencil component library has already been published to npm.
Is there a way to integrate stencil components locally into a framework to test them without publishing them first?
Yes, you can use npm-link for that.
cd my-component-lib
npm link
cd ../my-app
npm link my-component-lib # or whatever you have named the project in package.json
If you have any problems with that (e. g. with paths not resolving properly), you can also try to pack your package and install the packed version instead, using npm-pack:
cd my-component-lib
npm pack
cd ../my-app
npm install ../my-component-lib/my-component-lib-1.0.0.tgz
Linking is preferable though because changes to your component library will be reflected immediately (after a rebuild), whereas with packing you'd have to re-pack and re-install it after every change to your lib.
Instead of publishing or packing your packages, you could utilize TypeScript's path mapping feature.
This allows you to write your import statements just as you would with a published package, but behind the scenes TypeScript maps the imports to their given source code location.
Here's an example of a tsconfig.json with path mapping added to the compiler options:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"ui-components": ["libs/ui-components"],
"ui-components/loader": ["libs/ui-components/dist/loader/index.cjs.js"],
"ui-components-react": ["generated/ui-components-react/src/components.ts"]
},
...
As you can see, it has 3 mappings: the path to the core Stencil components ui-components, the path to the generated React components which are exposed as ui-components-react, as well as the generated loader ui-components/loader which provides the bridge between the Custom elements and the React wrappers.
I created a full working example for Stencil Web Components with generated bindings and wrappers for React that comes without the need of publishing any package: Nx Stencil React.
Please note that this answer is based on #stencil/core 1.14.0 or below. Future versions may have a different approach on generating the framework integrations.
I've had quite a bit of trouble with this myself so will provide an answer specifically for Vue 3 as Stencil's Framework Integrations guide seems to refer only to Vue 2.
Starting Projects
Stencil Component
Following the Getting Started guide run npm init stencil. Choose the component option.
There was a bug in v2.7.0 so I update to v2.8.0 with npm i #stencil/core#latest --save-exact
Build the project with npm run build
Optional
By default, the stencil project configures multiple build targets, to make it easier to see what build files are being used you can edit the stencil config to only include the custom elements bundle:
\\ stencil.config.ts
outputTargets: [
{
type: 'dist-custom-elements-bundle',
},
{
type: 'dist',
esmLoaderPath: '../loader',
},
],
You also need the 'dist' type for the .d.ts typings file to be generated with your custom-elements (not sure why).
Vue 3 App
Using a globally installed Vue CLI #vue/cli#4.5.13 create a new Vue 3 default project.
Using Stencil in Vue 3
Install your stencil component project
npm install --save ../<path>/stencil-component as a dependency of your vue app.
Fixing NPM Module Resolution
Following the Vue CLI - Troubleshooting guide add a vue.config.js file to the root of your Vue 3 project with the line config.resolve.symlinks(false),
Skipping Component Resolution
In the same file we need to configure Using Custom Elements in View
\\ vue.config.js
module.exports = {
chainWebpack: (config) => {
config.resolve.symlinks(false),
config.module
.rule("vue")
.use("vue-loader")
.tap((options) => ({
...options,
compilerOptions: {
isCustomElement: (tag) => tag.includes("my-"),
},
}));
},
};
Framework Integration
Now we can declare the custom elements, but in the Vue 3 way
\\ main.js
import { createApp } from 'vue'
import App from './App.vue'
import { defineCustomElements } from "stencil-component";
defineCustomElements();
createApp(App).mount('#app');
You can now use your custom component as normal. Here's what my App.vue file looked like after hacking the example starter code:
<template>
<my-component first="Andy" middle="2K" last="11"></my-component>
</template>
<script>
import { MyComponent } from "stencil-component";
export default {
name: 'App',
components: {
MyComponent
}
}
</script>
Errors
No ESLint Config
No ESLint configuration found in /<path>/stencil-component/dist/custom-elements.
Fixed by telling webpack not to resolve symlinks in vue.config.js
Uncaught TypeError: class constructors must be invoked with 'new'
This error occurs in the browser after a successful compilation.
Resolved by telling webpack / vue not to resolve your custom components
Custom Component Not Visible
There are no errors and your component is showing in the DOM inspector but not appearing on the page.
You need to defineCustomElements() in main.js.
Component not found
I've had some variation of this error when trying to import and use my component but haven't been able to reproduce it just now. Doing all of the above and restarting the dev server works fine for me.
For local integration, you can reference the esm.js file inside www/build folder which can be used in the head tag of the Vue/React project.
For eg if you have the below 2 apps
stencil-components - stencil components
stencil-react - sample react app which will consume the components.
Once you run stencil-components by npm run start it will be hosted at 3333 (by default).
Including below line in head ofindex.html of stencil-react will integrate components with live reloading on change.
<script type="module" src="http://localhost:3333/build/stencil-components.esm.js"></script>

Unable to compile react application as it says "Module not found"

I have been trying to execute a very simple react application, but for some reason I'm unable to compile it. When i try to compile it in bash using "npm start", i get the error stating "Failed to compile: ./src/index.js
Module not found: Can't resolve './registerServiceWorker' in '/Users/Pruthvi/Desktop/ReactApplication/my-app/src'"
can anybody help me as I am a new bee to react application!
By default, create-react-app will create a progressive web app, as documented here. The progressive web app relies on registerServiceWorker() in the registerServiceWorker.js file. You have apparently deleted this file, so your project no longer builds.
You have two choices:
Keep your project as a progressive web app, in which case you should simply restore the original state you had after first creating.
Opt out of the progressive web app features.
In order to opt out of the progressive web app features, you need to modify your src/index.js file as follows:
Delete the import of the registerServiceWorker.
Delete the registerServiceWorker() call.
Your src/index.js will then look like this:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
// Deleted -- import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
// Deleted -- registerServiceWorker();
Once you've made those modifications to your index.js, you can safely delete the registerServiceWorker.js file (which it appears you've already done based on the error message you've posted).
The documentation gives a more complete description of how to opt out and some of the consequences of having a progressive web app.
If you are new to react and need to build apps fast you can try
create-react-app by facebook
it a command line tool that will help you build better react app fast with zero configuration you can learn more from the link above and its easy to use
also make sure that you use a good editor that can help you catch errors
and to help you and give you good answer the second time please provide your code to understand the problem well .

Unit test React Native app that uses Native Modules with Jest

I'm trying to test my React Native app with Jest. My app uses a few Native Modules and I can't even run the initial test.
My app uses the component react-native-camera that has native dependencies.
The initial test:
import 'react-native';
import React from 'react';
import Index from '../index.ios.js';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('renders correctly', () => {
const tree = renderer.create(
<Index />
);
});
When I run it, I get the following error:
FAIL __tests__/index.android.js
● Test suite failed to run
TypeError: Cannot read property 'Aspect' of undefined
at Object.<anonymous> (node_modules/react-native-camera/index.js:250:78)
How can I bypass this type of error causes by native modules? Shallow rendering or similar?
I use RN 0.39.
Thanks
It's described in the Jest docs for react-native now:
https://facebook.github.io/jest/docs/tutorial-react-native.html#transformignorepatterns-customization
The transformIgnorePatterns option can be used to whitelist or blacklist files from being transformed with babel. Many react-native npm modules unfortunately don't pre-compile their source code before publishing.
By default the jest-react-native preset only processes the project's own source files and react-native. If you have npm dependencies that have to be transformed you can customize this configuration option by whitelisting modules other than react-native:
"transformIgnorePatterns": [
"node_modules/(?!react-native|my-project|react-native-button)/"
]
There is also an issue on github within the react-native project that discusses this issue: https://github.com/facebook/jest/issues/2382
Hope this helps

Categories