jQuery in react component - javascript

I have a web-app built with react. In this app I also have some pages with jQuery code from an old version. Right now this is rendered server side and i have to load the entire ejs file with jQuery and jQuery-UI code in script-tags with its own navigation menu. (Almost 1000 lines of jQuery code)
This means that I have to build another nav-menu for these jQuery pages.
I would like to render this jQuery depended code in my "content div" so I can still use the react menu which uses react router. I would like to render it like a component. But I don't know if this is the best solution.
I have read many examples of how this could be done, but I don't know which of them to go for and I have been strugling to make them work
Like shown in this example: Adding script tag to React/JSX This example adds script tags in componentWillMount
Or with import and require like this example: How to add script tag in React/JSX file?
I couldn't make these solutions work without installing jQuery through npm.
I have not yet installed jQuery through npm because I know this will affect my bundle size for the rest of the application and I am only using jQuery for a couple of my pages. The user don't really need to load jQuery for the rest of the app
What do you recommend in a situation like this? What is the best solution for performance and user experience?

Take a look at react-async-component. Your component might look something like:
// SomethingWithJquery.js
import React, {Component} from 'react'
import $ from 'jquery'
class SomethingWithJquery extends Component {
constructor(props) {
super(props)
}
render() {
// ... as much jquery mess as you need
}
}
export default SomethingWithJquery
And wrapper in separate file:
// SomethingWithJquery.async.js
import { asyncComponent } from 'react-async-component';
export default asyncComponent({
resolve: () => System.import('./SomethingWithJquery')
});
Than you can use it as regular react component, react-async-component will load entire component in separate .js file on purpose under the hood.

Related

How to lazy load Angular Components of the home page?

I have my code as given below in app.component.html i.e. as soon as the user lands on the home screen; I want to lazy load the app-image-gallery & app-users-list and want to load them with some Shimmer effect or Loader as soon as the user reaches the viewport of that particular component. Almost every grown up site use this but this thing is kind of difficult to find for Angular.
I have read many articles on lazy loading of component on button click but haven't found this thing implemented anywhere.
app.component.html
<app-navbar></<app-navbar>
<app-image-gallery></app-image-gallery> //list of images from backend
<app-users-list></app-users-list> //users list from backend
<app-faq></app-faq>
UPDATE(2022) -
After a lot of reasearch, I found these awesome packages for Angular lazy loading of components because packages like #herodevs/hero-loader & ngx loadable are deprecated for newer versions of angular. I will also attach the link to their articles-
#angular-extensions/elements
#juristr/ngx-lazy-el
ngx-element
Articles-
#juristr/ngx-lazy-el
#angular-extensions/elements
These packages are suitable for Angular 9+ versions. I hope it helps someone. And suppose if you want to load components on scroll, On Scroll Load, this is the thing you are looking for and each solution fully tested.
This solution is been tested with angular 9 and above with ivy.
If you are using older version of angular checkout this article:
https://pretagteam.com/question/load-new-modules-dynamically-in-runtime-with-angular-cli-angular-5
Angular 9+ solution:
Before you start you should make sure that your lazy loading components are in a separated module which is not imported in your app module.
First you need to pick a container element and mark it with a template variable to render your lazy component inside it.
Something like:
<div #container></div>
And then in your component class you need to query this container using #ViewChild as ViewContainerRef:
#ViewChild('container', {read: ViewContainerRef}) container: ViewContainerRef;
Now you are ready to lazy load your component using the webpack dynamic import. which as by default available in an angular app.
Then you will need to resolve the component factory using the angular ComponentFactoryResolver after you inject it in your component constructor.
And at the end you will just render the component factory in the view reference you have prepared this.container:
lazyLoadAppImageGallery() {
import('path/to/your/app-image-gallery-component')
.then(({AppImageGallery}) => {
const componentFactory =
this.componentFactoryResolver.resolveComponentFactory(AppImageGallery);
const { instance } = this.container.createComponent(componentFactory);
});
}
After you have rendered your component you might want to pass some data to it.
You could use the instance for this:
instance.propertyName = someValue
Checkout this nice article for more infos:
https://medium.com/#ckyidr9/lazy-load-feature-modules-without-routing-in-angular-9-ivy-220851cc7751
Update
Here is a working solution with dynamic render on scroll
https://stackblitz.com/edit/angular-ivy-megwrz
If you might use lazy loading with routes, just checkout angular simple documentation
https://angular.io/guide/lazy-loading-ngmodules
You could also combine both solutions. In case you want to dynamically load a component in a lazy loaded module loaded by route.
Update since Angular v13
Since v13 ComponentFactoryResolver is deprecated. Create component does require resolving component factory. You can use the component class directly thanks to the Ivy engine. Which means instead of writing:
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(AppImageGallery);
const { instance } = this.container.createComponent(componentFactory);
you could just write:
this.viewContainerRef.createComponent(AppImageGallery);

Should we import a whole library or a specific individual component when using along Create-React-App?

I am asking this on performance/optimizing issue. I realize that all libraries (and their default export method) are different but for example on react-bootstrap's doc intro it states that
You should import individual components like: react-bootstrap/Button rather than the entire library. Doing so pulls in only the specific components that you use, which can significantly reduce the amount of code you end up sending to the client.
Since we are in 2019, does Create-React-App's (CRA) build automatically optimize for us and only import those components who have been used at least once?
If so, does that mean that we can ignore the advice and import the whole library instead of specific components?
Here are the two examples given by the docs:
import Button from 'react-bootstrap/Button';
This is the recommended way to import. In this case, you are explicitly importing the component from the library.
// or less ideally
import { Button } from 'react-bootstrap';
This method imports the entire library and adds the Button component to the scope of that file. This case uses Webpack's tree shaking functionality to reduce the bundle size, which is not entirely reliable. This article provides insight on why that's the case: https://advancedweb.hu/2017/02/07/treeshaking/

How to make component tags start with a prefix in Vue?

I am working on a project that I inherited from someone else, and I see a lot of <p-xxxx> tags, such as <p-page :has-something="val1" :has-another="val2" />, etc.(e.g. CompName -->
I'm looking around the directories and found a component called Page.vue that has such props in it: has-something and has-another. And structurally speaking, I'm sure the <p-page> corresponds to this component.
So how did this work? I checked the component's name field and it says Page.
EDIT:
I should also note that the component isn't registered at all. It's not imported either. I'm guessing it has something to do with
import '#/globals';
import '#/plugins';
in main.js, because I know we're using our proprietary UI component library. Can anyone point to where I can go read more about how this works? I thought I was pretty good at Vue, but apparently not good enough.
It depends on how the component is registered in the parent component, for instance, if the Page component is registered as:
components: {
PPage: Page
}
Then in the template, you'll refer to this component as <p-page ...
I figured it out.
In our proprietary library we're using, components were being exported out with p- as a prefix, and the library was injected into the whole app via vue.config.js, so there wasn't any importing in individual components.

How to add/use React component in only one part (cart page) of my existing node project?

Up until now I have been using create-react-app to build React applications and components.
However, I have a project that I'm working on which was built in node using pure JS for Dom manipulation and I wanted to add react to one page only (the cart page).
All tutorials I had watched assume you are starting project from scratch and I can't seem to figure out how to add React to just a single part of my project.
Can someone point me in the right direction?
I would recommend you start here:
https://reactjs.org/docs/rendering-elements.html
The React Docs actually also point at this tutorial for a non 'create-react-app' tutorial: https://blog.usejournal.com/creating-a-react-app-from-scratch-f3c693b84658
This is the React Docs for rendering elements. The TLDR version:
In your HTML file, where you want your React component to go, create an empty div and give it a unique name (i.e. 'app' or 'react-component')
Then create your component, etc. and have ReactDOM render on the unique id name.
To get it to render, in your node app, point it at the build path, typically bundle.js
I have got this working and managed to use React components (written in JSX) for specific parts of my custom JavaScript app (bundled via Webpack). You basically need three things.
1) Your custom JavaScript app
// MyApp.js
import { renderMyReactComponent } from "./MyReactComponent.jsx";
class MyApp {
// Call this when you want to show your React component
showMyReactComponent() {
// Create an empty div and append it to the DOM
const domElem = document.createElement("div");
domElem.classList.add("my-react-component");
document.append(domElem);
// Render your React component into the div
renderMyReactComponent(domElem);
}
}
2.) Your React component
// MyReactComponent.jsx
import React from "react";
import ReactDOM from "react-dom";
class MyReactComponent extends React.Component {
render() {
// JSX, woah!
return <h2>My React Component</h2>
}
}
// A way to render your React component into a specific DOM element
export const renderMyReactComponent = (domElem) => {
// NB: This syntax works for React 16.
// React 18 requires a slightly different syntax.
ReactDOM.render(
<MyReactComponent />,
domElem
);
}
3.) A way to parse jsx files and build the app
I use Webpack and amended my existing Webpack configuration based on this article: https://medium.com/#JedaiSaboteur/creating-a-react-app-from-scratch-f3c693b84658 (The official React documentation also points at this tutorial)
Useful Articles
A good read is this article from the official React documentation: https://reactjs.org/docs/add-react-to-a-website.html. This also explains a different way to integrate a React component into your existing JavaScript app using script tags instead of Webpack.
You might also be interested in this answer to a similar question as yours.
As #pinkwaffles pointed out in their answer, the following article helps to understand rendering a React component into a DOM element: https://reactjs.org/docs/rendering-elements.html
PS: Note that at the time of writing this answer, the above articles already use React 18 for their examples, whereas my above example still uses React 16; so the syntax regarding ReactDOM is a little different. But the idea is the same.

vuejs include javascript library in spa

i'am creating spa application using vuejs and i find out that i have 3 option in loading my javascript library like bootstrap.js or jquery.js and other javascript library:
1.
first is by include all javascript library that i will use in my application in index.html where my vuejs application will live but i find that there is some javascript library that not working to well
ex: there is some javascript library that calculate page height by selecting some div with specific id="page-container", but that div not loaded when page is rendered from server, so at that moment the javascript will throw error since id="page-container" not exist yet.
2.
second is by adding it like this to all my javascript library js
// before you use your files in some components,you should package them
// your local files
export default { //export your file
your_function(){ // defined your function
...
}
}
// now your can use it
// your component file
<script>
import local_file from 'your_file_relative_path'
//now you can use it in the hook function
created(){ //or other hook function
local_file.your_function() //call your function
}
</script>
but that mean i need to change every javascript library that i use...
3.
third is by adding it using npm, and just in the vue component import it, it works okay and feels more natural but not all my javascript library are in npm, some of them is admin template related that i bought from themeforest and will never be in npm.
so which one is a better way or maybe there is much more better way that those 3 option that i find out? its hard to find any tutorial or discussion that mention adding other javascript library to spa vuejs most of them just put a bootstrap into index.html and done.
Well, If your library exist in NPM, then this is the best option, because then you have this option to import only the part of the script that you need for certain components, for example, fontawesome library, you can import only the icons that you need instead of import all of them!
but if your script is not in NPM, the best option is to run your script in beforeMount or beforeCreate of the component that the script needed to run.
the third way which is add the link reference on html is not really suggested, since it will be global and will reduce the performance.

Categories