Share React-Native components - javascript

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.

Related

Load JavaScript on specific page with #wordpress compiler

I'm new to WordPress development.
I have been following a tutorial in Udemy to build my new WordPress website. As recommended by the trainer, it is useful to use npm to package the JavaScripts using "#wordpress/scripts". The npm command monitors a single index.js file, which is then compiled into WordPress friendly version. Then in functions.php I added the wp_enqueue_script() function to call the index.js from build folder.
The problem: I have created multiple JavaScript files, which contain new classes with the required code and are imported into the main index.js file. Each parent JavaScript file is responsible for a specific functionality, e.g. I have MyLogin.js file which is responsible for handling user login and another file EditProfile.js which handles user profile editing functionality. The EditProfile.js should be called/instantiated only when the user is logged in and the MyLogin.js should be called/instantiated only when user is not logged in. According to the articles I have read online, I can use functions.php to enqueue specific JavaScript files when a user is on a specific page. This would work if I would not use the npm to package my JavaScripts into a single file, but how do I handle the load of required JavaScript files from a single bundled index.js file?
The only solution I thought of, was to create an evaluation statement in the index.js file to only call/instantiate the required class if the current page is home page or profile page respectively, but to me it seems as a bad coding practice.
Can you please guide me to the right direction?
P.S. Is it even worth to use "#wordpress/scripts" to compile everything into a single file?
Here is my index.js file
import "../css/general.css";
import "../css/style.css";
import "../css/queries.css";
import "../css/profile.css";
import "../css/login.css";
import "../css/front-page.css";
import EditProfile from "./modules/EditProfile";
import MyLogin from "./modules/MyLogin";
const myLogin = new MyLogin();
const editProfile = new EditProfile();
The logic I was thinking of would be something like this:
import "../css/general.css";
import "../css/style.css";
import "../css/queries.css";
import "../css/profile.css";
import "../css/login.css";
import "../css/front-page.css";
import EditProfile from "./modules/EditProfile";
import MyLogin from "./modules/MyLogin";
if (window.location.href == "https://<site_url>") {
const myLogin = new MyLogin();
}
if (window.location.href == "https://<site_url>/profile") {
const editProfile = new EditProfile();
}

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

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

npm is only updating when changes are made in index.js

I have just started learning React and I am running the server with the command npm start but the problem is whenever I am making any changes in the index.js file it is updating it on the website but whenever I am importing some other apps and making changes in those apps it is not updating the website .
How can I update my site on updating any file in the project ?
Here is my header.js file
import React from 'react';
const user = {
name : 'Brijesh',
lastname : 'Maurya',
age : 20
}
const Header = () =>{
return (
<div>
<div>{user.name}</div>
</div>)
}
export default Header;
Here is index.js file
import React from 'react';
import ReactDOM from 'react-dom';
// Components
import Header from './components/header'
const App = () =>{
return (
<div>
<Header/>
</div>
)
}
ReactDOM.render(<App/>, document.querySelector('#root'));
As your issue is resolved by creating another app , maybe you should think over the flow you went through while making those files .
As you mentioned that you have just started learning react , I think you might have done something like deleting all the files and then creating new files from scratch.
Anyways , welcome to the world of React JS !
It sounds like whatever server npm start is running - probably a node server - has Hot Module Replacement configured and for the other apps that you are running HMR is not configured.
You can learn more about how to configure HMR on Webpack's site here:
https://webpack.js.org/concepts/hot-module-replacement/
And about React Hot Loader here:
https://gaearon.github.io/react-hot-loader/getstarted/
If npm start runs the wepack-dev-server it may be as simple as running the server with the --hot flag.

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 .

Dynamically loading React components

I'm thinking about building a web application, where people can install plugins. I'd like plugins to be able to define React components that will be rendered to the page, without recompiling the main JavaScript bundle after installing the plugin.
So here's the approach I'm thinking of:
Bundle the main JavaScript with React as an external library, using webpack.
Have plugin authors compile their components with React as an external library as well.
This way, I'm only running one instance of React. I could probably do the same with some other frequently used libraries.
The problem then, is how to dynamically load these plugin components from the server. Let's say I have the following component:
class PluginRenderer extends React.Component{
componentWillMount() {
getPluginComponent(`/plugins/${this.props.plugin}/component.js`).then((com) => {
this.setState({pluginComponent: com});
})
}
render() {
var Plugin = this.state.pluginComponent;
return Plugin ? <Plugin {...this.props} /> : "Loading..."
}
}
How could getPluginComponent be implemented?
It's an interesting problem I also faced some months ago for customer work, and I didn't see too many document approaches out there. What we did is:
Individual plugins will be separate Webpack projects, for which we provide either a template or a CLI tool that generates project templates.
In this project we define Webpack externals for shared vendor libraries already used in the core application: React, Redux, etc. This tells the plugin to not include those in the bundle but to grab them from a variable in window we set in the core app. I know, sounds like sucks, but it's much better than having all plugins re-include 1000s of shared modules.
Reusing this concept of external, the core app also provides some services via window object to plugins. Most important one is a PluginService.register() method which your plugin must call when it's initialized. We're inverting control here: the plugin is responsible to say "hi I'm here, this is my main export (the Component if it's a UI plugin)" to the core application.
The core application has a PluginCache class/module which simply holds a cache for loaded plugins (pluginId -> whatever the plugin exported, fn, class, whatever). If some code needs a plugin to render, it asks this cache for it. This has the benefit of allowing to return a <Loading /> or <Error /> component when a plugin did not load correctly, and so on.
For plugin loading, this PluginService/Manager loads the plugin configuration (which plugins should I load?) and then creates dynamically injected script tags to load each plugin bundle. When the bundle is finished, the register call described in step 3 will be called and your cache in step 4 will have the component.
Instead of trying to load the plugin directly from your component, ask for it from the cache.
This is a very high level overview which is pretty much tied to our requirements back then (it was a dashboard-like application where users could add/remove panels on the fly, and all those widgets were implemented as plugins).
Depending on your case, you could even wrap the plugins with a <Provider store={ theCoreStore }> so they have to access to Redux, or setup an event bus of some kind so that plugins can interact with each other... There is plenty of stuff to figure out ahead. :)
Good luck, hope it helped somehow!
There is a HOC component that you can import to do this. Components are dynamically loaded as micro apps into your host application.
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
window.React = React;
window.ReactDOM = ReactDOM;
ReactDOM.render(<App />, document.getElementById('root'));
// app.js
import React from 'react';
import ReactDOM from 'react-dom';
import MicroApp from '#schalltech/honeycomb-react-microapp';
const App = () => {
return (
<MicroApp
config={{
View: {
Name: 'redbox-demo',
Scope: 'beekeeper',
Version: 'latest'
}
}}
/>
);
});
export default App;
The components are not installed or known at design time. If you get creative, using this approach you could update your components without needing to redeploy your host application.
https://github.com/Schalltech/honeycomb-marketplace#using-micro-apps
I presented an alternative approach on a similar question. Recapping:
On your app
import(/* webpackIgnore: true */'https://any.url/file.js')
.then((plugin) => {
plugin.main({ /* stuff from app plugins need... */ });
});
On your plugin...
const main = (args) => console.log('The plugin was started.');
export { main };
export default main;
See more details on the other question's page.

Categories