I am trying to convert bootstrap 4 template into reactjs bootstrap is working fine but there are other javascript plugins also and I don't know how to use .
Any suggestions would be appreciated.
Update: Please, don't mix jQuery and React. It could be difficult to handle the DOM and VirtualDOM. Just try it if you really need to:
Try to invoke the scripts and append it when componentDidMount at Root component. Here is a snippet:
//#Write some like this in the App.js for example, since it's the main component:
componentDidMount(){
//An array of assets
let scripts = [
{ src: "assets/vendor/jquery/jquery.js" },
{ src: "assets/vendor/bootstrap/js/bootstrap.js" },
{ src: "assets/vendor/jquery-placeholder/jquery.placeholder.js" },
{ src: "assets/javascripts/theme.js" },
{ src: "assets/javascripts/theme.custom.js" },
{ src: "assets/javascripts/theme.init.js" }
]
//Append the script element on each iteration
scripts.forEach(item => {
const script = document.createElement("script")
script.src = item.src
script.async = true
document.body.appendChild(script)
})
}
Include the script tag in your index.html
Let's say if you want to include JQuery in your ReactJs app
Include following in index.html
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
Use this in following code and it works well
import React, { Component } from 'react';
class App extends Component {
constructor(){
super()
this.callJquery = this.callJquery.bind(this);
}
callJquery(){
window.$("#sample").click(function(){
alert("Text: Button Clicked");
});
}
render() {
return (
<div className="App">
<div id="sample" onClick={this.callJquery}> Hellow </div>
</div>
);
}
}
export default App;
Similarly, you can use any library by including in index.html and then use it.
Related
I have open source library that I want to use. the library wrote in clean vanilla js:
follow their docs, if I want to use the library:
<html>
<head>
<script src="./jquery-2.0.3.min.js"></script>
<script src="./kinetic-v5.1.0.min.js"></script>
<script src="./inchlib-1.2.0.js"></script>
<script>
$(document).ready(function() { //run when the whole page is loaded
var inchlib = new InCHlib({"target": "inchlib",
"width": 800,
"height": 1200,
"column_metadata_colors": "RdLrBu",
"heatmap_colors": "RdBkGr",
"max_percentile": 90,
"middle_percentile": 60,
"min_percentile": 10,
"heatmap_font_color": "white",
text: 'biojs'});
inchlib.read_data_from_file("/microarrays.json");
inchlib.draw();
inchlib.onAll(function(name){
console.log(name + " event triggered");
});
});
</script>
</head>
<body>
<div class="heatmaps" style="margin:auto; align-items: center; margin-left:25%;">
<div id="inchlib"></div>
</div>
<div ></div>
</body>
</html>
The file inchlib-1.2.0.js contains the main logic and js code. I want to build react project and use this library there. How can I achieve this goal?
import React, { Component } from 'react';
import './App.css';
export default class App extends Component {
render () {
return (
<div>
<div>
</div>
</div>
)
}
}
You can create custom hook with useEffect. In useEffect you should paste your code. You can insert html elements, add event listeners and so on.
useLibrary.js
import { useEffect } from "react";
const useLibrary = () => {
useEffect(() => {
$.getScript("inchlib-1.2.0.js", function(){
var inchlib = new InCHlib({"target": "inchlib",
"width": 800,
"height": 1200,
"column_metadata_colors": "RdLrBu",
"heatmap_colors": "RdBkGr",
"max_percentile": 90,
"middle_percentile": 60,
"min_percentile": 10,
"heatmap_font_color": "white",
text: 'biojs'});
inchlib.read_data_from_file("/microarrays.json");
inchlib.draw();
inchlib.onAll(function(name){
console.log(name + " event triggered");
});
});
}, []);
};
export default useLibrary;
App.js
import useLibrary from ".useLibrary";
export default class App extends Component {
useLibrary();
render () {
return (
<div>
<div class="heatmaps" style="margin:auto; align-items: center; margin-left:25%;">
<div id="inchlib"></div>
</div>
</div>
)
}
}
But I warn you that this is a big crutch.
Depends on what you're gonna do with the library you want to integrate with. Checkout this as a base reference: Integrating with other libraries.
If you're gonna manipulate DOM elements you'll gonna need a reference to them. In this case checkout this: Refs and the DOM.
If the library provides some general logic, you have no problem using it anywhere throughout your code or more specifically in effects.
As inchlib is a visual element library, you'll need to go the first route and get a reference to a specific DOM element. As already noted, checkout Refs from react docs.
Alternative solution is to wrap the whole library usage in your own react component.
Well If I were to do the same thing then I would paste the script tags as you've done in your html file
<head>
<script src="./jquery-2.0.3.min.js"></script>
<script src="./kinetic-v5.1.0.min.js"></script>
<script src="./inchlib-1.2.0.js"></script>
<script>
</head>
For accessing an object into react app, Create a file named Inchlib.js in same directory as is your app.js
Contents of Inchlib.js should be
export default window.InCHlib;
Import the default export into your app.js
import InCHlib from "./inchlib";
function App() {
console.log(InCHlib); // prints the InCHlib object
return "hello";
}
Note: Although this should work, there might be a better way to do this. Also using global objects in react code is not usually a preferred option.
Hopefully this would help.
Just add the Libraries and Scripts you want in the public/index.html file in your react project.
create loadScript function:
function loadScript(src, position, id) {
if (!position) {
return;
}
const script = document.createElement('script');
script.setAttribute('async', '');
script.setAttribute('id', id);
script.src = src;
position.appendChild(script);
}
in Component:
export default function GoogleMaps() {
const loaded = React.useRef(false);
if (typeof window !== 'undefined' && !loaded.current) {
if (!document.querySelector('#google-maps')) {
loadScript(
'https://maps.googleapis.com/maps/api/js?key=AIzaSyBwRp1e12ec1vOTtGiA4fcCt2sCUS78UYc&libraries=places',
document.querySelector('head'),
'google-maps',
);
}
loaded.current = true;
}
}
now you can access window.google
here is a example
I have a vuejs app as a container for multiple other "apps".
The idea was to:
have a generic code to discover/load components
build the other apps as vuejs lib in order to be able to load component on it
On my first lib, I have this main.js:
import HelloRadar from './components/HelloRadar.vue'
export default HelloRadar
and this component, HelloRadar:
<template>
<div>
Hello from radar !
</div>
</template>
<script>
export default {
name: 'HelloRadar'
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
Now, on my main app, I have this code:
<template>
<div>
<ul>
<li v-for="module in modules" v-bind:key="module" #click="loadModule(module)">
{{ module }}
</li>
</ul>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'HelloWorld',
data() {
return {
modules: [],
selectedModuleMenu : null,
selectedModuleApp : null
}
},
created: function () {
axios.get("/orbit/api/modules").then((response) => {
var modulesList = response.data;
this.modules = modulesList;
});
},
methods: {
loadModule: function (moduleName) {
this.loadExternalComponent("/modules/" + moduleName + "/"+ moduleName + ".umd.js");
},
loadExternalComponent : function(url) {
const name = url.split('/').reverse()[0].match(/^(.*?)\.umd/)[1];
if (window[name]) return window[name];
window[name] = new Promise((resolve, reject) => {
const script = document.createElement('script');
script.async = true;
script.addEventListener('load', () => {
resolve(window[name]);
});
script.addEventListener('error', () => {
reject(new Error(`Error loading ${url}`));
});
script.src = url;
document.head.appendChild(script);
});
return window[name];
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
The issue is that the function loadExternalComponent seems not working. I got this js error in console:
Uncaught TypeError: Cannot read property 'createVNode' of undefined
Uncaught (in promise) TypeError: Chaining cycle detected for promise #
I have picked this method from here https://markus.oberlehner.net/blog/distributed-vue-applications-loading-components-via-http/
Do you have some idea how to make this kind of app ? Does using lib is the right way ? Thanks for your help
I think there's an answer to your question:
Components built via the Vue 3 vue-cli rely on Vue being available in
the global scope. So in order to render components loaded via the
technique described in my article, you need to set window.Vue to a
reference to Vue itself. Then everything works as expected.
Markus Oberlehner
#moriartie (Markus Oberlehner) has already worked that out with #markoffden: Vue 3 external component/plugin loading in runtime
I have to display dynamic meta descriptions for my articles and I am kind of struggling to achieve that with the async function for my head object. This is what I have so far:
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
#Component
export default class ArticleContent extends Vue {
article: any | null = null;
articlelist = example.data;
async asyncData({params: any }) { <----- Not sure how I could put in my articlelist here
return this.articlelist;
}
head(): object {
return {
title: this.articlelist.productId.productNames['en'],
meta: [
{
hid: this.articlelist._id,
name: this.articlelist.productNames['en'],
content: this.articlelist.metaDescription['en'],
},
],
};
}
}
</script>
articlelist is what I am using in the head() object for my meta description. Would appreciate some help!
Both the head() and asyncData() properties are not part of the core of vue,
to use head() you need to install this as a plugin
to use asyncData() you have to use nuxt
If your spa has a strong need for seo I suggest you use nuxt, which natively includes seo and the conversion from vue to nuxt is very easy
If you already using nuxt this is the correct way to get
async asyncData({params: any }) {
const articlelist = await axios.get('some.url'); //get the data
return { articlelist }; //this object is merged with the data of the istance
}
Fetching dynamic HTML from an API, the HTML is loading fine but the CSS is not working for this new HTML.
Do you I need to reload the CSS.
import React, { Component } from "react";
import Utility from "../common/Utility";
class Template extends Component {
constructor(props) {
super(props);
this.token = localStorage.getItem("token");
this.client_id = localStorage.getItem("client_id");
}
componentDidMount() {
//fetching dynamic html
Utility.ExecuteData("template", this.token, {
client_id: this.client_id
}).then(result => {
var dynamic_html = document.getElementById("dynamic_html");
dynamic_html.innerHTML = result.data[0].template;
});
}
render() {
return (
<React.Fragment>
<div id="dynamic_html" />
</React.Fragment>
);
}
}
export default Template;
It is possible to get this to work but instead of className you'll need to use the usual HTML class attribute. I've used dangerouslySetInnerHTML here, but it's the same result if you set the innerHTML of the element like you did in your question.
function Template({ html }) {
return (
<div dangerouslySetInnerHTML={{__html: html}} />
);
}
const html = '<div class="heading">With style</div>';
ReactDOM.render(
<Template html={html} />,
document.getElementById('container')
);
.heading {
font-size: 2em;
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="container"></div>
I can't comment so I'm posting it in an answer instead.
I don't know how the html is being returned from the API but I assume the css is either inlined or included as a file in the remote HTML.
If the latter is the case, it might be a possibility that the url to the css file is relative, so calling the url from another server would result in a 404.
For simple html projects i can simple refer this link.
https://www.w3schools.com/howto/howto_google_translate.asp
But I'm trying to implement in react app . So I'm not able to replicate the code in react app.
componentDidMount() {
googleTranslateElementInit(() => {
new google.translate.TranslateElement({pageLanguage: 'en'}, 'google_translate_element');
});
const script = document.createElement("script");
script.src = "//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit";
script.async = true;
document.body.appendChild(script);
}
And return render element .
render() {
return (
<div id="google_translate_element"></div>
);
}
This is showing me error saying google , googleTranslateElementInit is not defined.
How can I use google translator in react app ?
Also is there any npm packages which can translate whole site ?
Thanks
Move your google translate script to the root index.html of your project.
However, you should leave the below code at your desired location:
render() {
return (
<div id="google_translate_element"></div>
);
}
Fixes the problem easily.
Change render to:
render() {
return (
<script type='text/javascript' src='//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit' />
<div id="google_translate_element"></div>
);
}
Create googleTranslateElementInit and use window.google instead of google:
googleTranslateElementInit () {
/* eslint-disable no-new */
new window.google.translate.TranslateElement({pageLanguage: 'pt', layout: window.google.translate.TranslateElement.FloatPosition.TOP_LEFT}, 'google_translate_element')
}
Change componentDidMount to:
componentDidMount () {
window.googleTranslateElementInit = this.googleTranslateElementInit
}
For those in 2021 and hopefully a few more years before Google decides to change implementation method, this is how I resolved it.
Add the below script to your index.html file found in the public directory:
<script src="https://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit" async></script>
<script type="text/javascript">
function googleTranslateElementInit() {
new google.translate.TranslateElement(
{
pageLanguage: "en",
layout: window.google.translate.TranslateElement.InlineLayout.VERTICAL,
},
'google_translate_element'
);
}
</script>
Then, create a component, to be imported anywhere you want to use the translate plugin, with any name of your choice. I will use GoogleTranslate.jsx for this purpose of this answer.
In the newly created component, paste this code:
import React, { useEffect } from "react";
const GoogleTranslate = () => {
useEffect(() => {
// in some cases, the google translate script adds a style to the opening html tag.
// this added style disables scrolling.
// the next 3 lines removes this added style in order to re-enable scrolling.
if (window.document.scrollingElement.hasAttribute("style")) {
window.document.scrollingElement.setAttribute("style", "");
}
});
return (
<div id="google_translate_element"></div>
);
};
export default GoogleTranslate;
Import the component wherever you want to use the translate plugin.
If this solution worked for you, kindly up vote so it can easily be shown to others searching. If it didn't, don't hesitate to drop a comment
Go to public folder > index.html
add code in body tag
<script type="text/javascript">
function googleTranslateElementInit() {
new google.translate.TranslateElement({pageLanguage: 'en', layout: google.translate.TranslateElement.InlineLayout.SIMPLE}, 'google_translate_element');
}
</script><script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
create component
import React from 'react';
import './style.css';
const GoogleTranslate = (props) => {
return(
<div id="google_translate_element"></div>
)
}
export default GoogleTranslate
import GoogleTranslate from './GoogleTranslate';
<GoogleTranslate />