Can't we inject component directly to App.js? - reactjs

I am newbie to web development.After I had finished html,css and js(basic things) I recently have started learning react js. On my first project setup src folder I see index.js and app.js files. Why we need index.js files here? Can't we inject component directly to App.js?

index is generally used to say communicate _this is the highest level within this directory/hiearchy. Index is the entry point to your application where it's bootstrapped in the DOM. App is just a component like any other component. You could call it anything, e.g., Root, ComponentNotNamedApp, etc.
You don't need both, but it keeps the index file clean without adding in a bunch of component code. In App, you may be wrapping things with contexts, them providers, adding in other components, etc.
My app uses redux, so all that's in index is this,
ReactDOM.render(
// redux stuff
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)

Related

Webpack config with two entry points, one for app the other for federate module

So I have a pretty standard create-react-app setup. Using craco to modify my webpack config. What I would like to achieve is two separate output files.
Just my standard index.html rendered react app.
a module file that would allow my to inject my react app into external app (such as in a micro front end system).
So for example I have a module file like
// module.ts
import App from "./app.tsx"
export function bootstrapComponent(divId) {
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById(divId),
);
}
I would like to bundle this and have my second "container-app" consume this at runtime, and run this function so that it could inject the subapp into the greater app.
Having a bitt trouble with setting this up with webpack.

Error: useRoutes() may be used only in the context of a <Router> component

I'm adding React modules dynamically using System JS, and it works great!
Except if I try to use the react-router context from the loaded module.
"react-router-dom": "6.0.0-beta.0"
You can see in the react component explorer that there is definitely a <Router> component as an ancestor.
The routing works fine in the host application - it only breaks when called from a dynamically loaded component.
I'm a novice with React, so I could be making a wrong assumption of how the contexts are provided to deeply nested or dynamically loaded children.
Router is mounted here -
https://github.com/savantly-net/sprout-platform/blob/47cb99f7076bf6df09d9fec8e2d6c7ee78ce08af/frontend/apps/webapp/src/index.tsx#L204
Module is being loaded here -
https://github.com/savantly-net/sprout-platform/blob/47cb99f7076bf6df09d9fec8e2d6c7ee78ce08af/frontend/apps/webapp/src/features/plugins/AppRootPage.tsx#L84
The module element that throws the exception is here -
https://github.com/savantly-net/sprout-platform/blob/47cb99f7076bf6df09d9fec8e2d6c7ee78ce08af/backend/modules/forms/src/plugin/FormsRootPage.tsx#L47
The problem was due to having the react-router-dom lib in the module bundle.
When the dynamic module loaded, it was using it's own version of the lib, rather then the one provided by the host application.
I added this to the externals in my webpack/rollup config, and the problem was solved.
I can now have children routes managed by a plugin inside a host application! =].
Webpack -
https://github.com/savantly-net/sprout-platform/blob/e746085ebd65820fd449c968385913f2cc86ee0d/frontend/tools/sprout-toolkit/src/config/webpack.plugin.config.ts#L176
Wrapping <App /> inside <Router> </Router> will resolve the issue.
import { BrowserRouter as Router } from "react-router-dom";
<Router>
<App/>
</Router>

Embed react component into website without Iframes

my company wants to create a react component which is going to render a google maps frame, a search field and a result list. Basically to search, see results and see them on the map.
Today the component is created but we're using a lot different libs like react-router, react-redux, axios, etc.
We want to find out a way to embed our component to another websites in a simple way without using iframes(if possible). Ideally a solution where we could just ask for our clients to add a div with a specific id and our script tab.
Any ideas how to solve it?
Thank so much.
In this situation, I'd suggest having Webpack bundle your component with whatever dependencies you need into a standalone js file. Then rather than using a typical app.js or index.js file that attaches an app to a body or div tag like create-react-app does, specifically use ReactDOM to render your component to a specific div based on ID. That way they just include your file and make sure they have the div with the ID and it'll take care of the rest. I've done something similar at a couple different jobs.
import ReactDOM from 'react-dom';
import MyComponent from 'my-component.js';
ReactDOM.render(<MyComponent />, '#my-div');
Besides that it's just tinkering with Webpack.
The consumer needs to tag an HTML element with an identifier in this case a class name representing a certain type of widget.
<div class="ray_widget"></div>
Then in the root of our react application src/index.tsx or jsx
We find all elements that are tagged and render react applications on it.
const WidgetDivs = document.querySelectorAll('.ray_widget')
WidgetDivs.forEach(divElement => {
const root = ReactDOM.createRoot(divElement);
root.render(
<React.StrictMode>
<Widget divElement={divElement} />
</React.StrictMode>
);
})
You then bundle your application and the customer needs to include the script on their website
<script src="https://your-react-app-bundle-cdn/index.js" type="text/javascript"></script>
Resource:
Embed React application without an iframe full post

Make React Component available as a Widget

I have a complicated React app (includes authentication to render certain components, etc) and there is a particular component, a date picker, which I would like other users to embed on their website as a Widget a la Google maps (<script src="my_widget"></script>).
I am already successfully sharing it as an iFrame, but I would like to learn how to do it as a 'proper' widget. Most of the solutions I found on SO were not to my understanding capabilities, perhaps I am pointed to a more noob solution.
FYI, I am using the create-react-app boilerplate code to load the React app:
ReactDOM.render(
<App />,
document.querySelector("#root")
);
You can create your react-app as it is. There are 2 more things that you'll need to make it work.
Provide a way to load or render your app on demand by the host page. For example rather than calling ReactDOM.render(<App />, document.querySelector("#root")); directly in the main app you can add a method like this:
const loadApp = (targetElement) => {
ReactDOM.render(<App />, targetElement);
};
You can expose this method using a global variable like this.
window.reactWidget.load = loadApp;
After that you'll need to create a JS snippet, which can load your bundled javascript file and call this function once the file is loaded from the network.
window.reactWidget.load(document.querySelector(#whatever'));

How to add Redux store to React Native app created using create-react-native-app

I've created a React Native app according to documentation, but when I want to add the Redux store, I find that there is no index.js or index.ios.js file to which I can wrap the Redux store.
When I create the index.js myself, I have no idea how to change the entry point of the application so it uses index.js instead of the default App.js. I feel like it should be something easy and obvious, but after googling for hours, it seems like I have two options. One, to use the App.js file like the index file, or to eject the application (which I don't want to do).
There is a file in the root called App.js, that is the entry point for your React Native App.
In there you should import/define your store and then, in the render method wrap your navigation solution with the Provider this way so that all your containers can be connected to redux:
render() {
return (
<View style={styles.container}>
<Provider store={store}>
<Navigation />
</Provider>
</View>
); }

Resources