How can I embed VaniilaJS into React? - javascript

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

Related

how to call react component code from renderer.js?

Hi I am new to React/JS and Electron and would like to write a desktop application using these technologies.
The problem I am facing now is that I am not sure how to call react component code from renderer.js. I have such coding structure.
electron-tutorial
src/
components/Test.js
application.js
electron-starter.js
mainWindow.html
package.json
And this is a list of code snippet of each file.
package.json:
"main": "src/electron-starter.js",
electron-starter.js
const application = require("./application");
global.application = new application();
global.application.run();
application.js
odule.exports = class Application {
createWindow() {
this.mainWindow = new BrowserWindow({
width: 1366,
height: 768,
...
pathname: path.join(__dirname, "./mainWindow.html"),
mainWindow.html
<body>
<div id="test"></div>
<script src="./renderer.js"></script>
</body>
So from mainWindow.html I want to call renderer.js. I learned that I know I can call functions in such way:
renderer.js
"use strict";
const { shell } = require("electron");
function hoge() {
console.log("hoge");
}
window.hoge();
But what I want to do is to call the react component below from renderer.js.
Test.js
import React from "react";
export class Test extends React.Component {
render() {
return <h1>Hello from Test class</h1>;
}
}
Could you please help me ? Thanks for reading !
As you are just starting out, I would recommend that you use a boilerplate like Electron-React.

How do I write script in React index.js?

I've been using basic HTML/CSS/JS so far, and now I tried using React/Gatsby.
I got API code from Kakao and confirmed the following code is working in index.html:
<body>
<div id="map" style="width:1000px;height:500px;"></div>
<script src="https://dapi.kakao.com/v2/maps/sdk.js?appkey=3199e8f198aff9d5aff73000faae6608"></script>
<script>{
var mapContainer = document.getElementById('map'),
mapOption = {
center: new kakao.maps.LatLng(37.56591, 126.97894),
level: 4,
mapTypeId : kakao.maps.MapTypeId.ROADMAP
};
var map = new kakao.maps.Map(mapContainer, mapOption);
}</script>
</body>
Since I'm trying React/Gatsby framework, I have to somehow reformat that script to index.js. HTML can be easily copy/pasted to return function, but I don't know how to write the above script in React index.js.
import React from "react"
export default class Home extends React.Component {
render() {
return (
<div style={{ color: `purple` }}>
<p>Welcome to donghwankim.com!</p>
<p>Powered by Gatsby</p>
<div id="map" style={{"height" : "1000px", "width" : "500px"}}></div>
<script src="https://dapi.kakao.com/v2/maps/sdk.js?appkey=3199e8f198aff9d5aff73000faae6608"></script>
<script>{
var mapContainer = document.getElementById('map'),
mapOption = {
center: new kakao.maps.LatLng(37.56591, 126.97894),
level: 4,
mapTypeId : kakao.maps.MapTypeId.ROADMAP
};
var map = new kakao.maps.Map(mapContainer, mapOption);
}</script>
</div>
)}
}
Few things I tried:
Just copy paste script like above. In this case, I get syntax error from the copied script:
Unexpected token. Did you mean {'}'} or &rbrace;?
Use dangerouslySetInnerHTML. There is no syntax error, but the map API is not working properly.
Thank you.
It seems like part of this script will need to be rewritten for React. You should look for a library for this that supports React. If there isn't one, you can use DOM refs to access the mapContainer without document.getElementById. Alternatively if you just want to use this script as-is, you can use a simpler static site generator like Jekyll that doesn't require you to use React.
2022 update
Since the release of the Script Gatsby component (powered by Partytown) it's much easier adding third-party scripts. Just:
import React from "react"
import { Script } from "gatsby"
function YourPage() {
return <Script src="https://my-example-script" />
}
export default YourPage
There's a lot of implementation there.
First of all, you need to load your script asynchronously using <Helmet> tag by using:
import React from "react"
import Helmet from "react-helmet"
export default class Home extends React.Component {
render() {
return (
<div style={{ color: `purple` }}>
<Helmet>
<script src="https://dapi.kakao.com/v2/maps/sdk.js?appkey=3199e8f198aff9d5aff73000faae6608" type="text/javascript"/>
</Helmet>
<p>Welcome to donghwankim.com!</p>
<p>Powered by Gatsby</p>
<div id="map" style={{"height" : "1000px", "width" : "500px"}}></div>
</div>
)}
}
Because of the asynchronous of your issue, you need to load a <div> container for your map and wait for its load, then you need to pass your map options. The preferred method in React, rather than document.getElementById (or similar), what retrieve directly values from the DOM, is using references. You'll need to use a componentDidMount() lifecycle to achieve it, since it's a method invoked that triggers immediately after a component is mounted (inserted into the tree):
import React from "react"
import Helmet from "react-helmet"
export default class Home extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
componentDidMount(){
const map= this.myRef.current;
const mapOption = {
center: new kakao.maps.LatLng(37.56591, 126.97894),
level: 4,
mapTypeId : kakao.maps.MapTypeId.ROADMAP
};
const yourMap = new kakao.maps.Map(map, mapOption);
}
render() {
return (
<div style={{ color: `purple` }}>
<Helmet>
<script src="https://dapi.kakao.com/v2/maps/sdk.js?appkey=3199e8f198aff9d5aff73000faae6608" type="text/javascript"/>
</Helmet>
<p>Welcome to donghwankim.com!</p>
<p>Powered by Gatsby</p>
<div id="map" ref={this.myRef} style={{"height" : "1000px", "width" : "500px"}}></div>
</div>
)}
}
Note: you may need to unmount the map to avoid excessive resource consumption. It depends on how the library is implemented and its documentation.
Recommended readings/references:
https://github.com/nfl/react-helmet
https://reactjs.org/docs/refs-and-the-dom.html
https://reactjs.org/docs/react-component.html#componentdidmount
https://reactjs.org/docs/state-and-lifecycle.html

VueJS; wait for element before running local JavaScript File

I have a few components, javascript, and elements that needs to be ran in a certain order.
1st - opensheetmusicdisplay.min.js which I have in my index.html file. This isn't an issue.
2nd - <div id="xml">
3rd - xml-loader.js which depends on both the "xml" div and opensheetmusicdisplay.min,js
This is the index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<script rel="preload" src="<%= BASE_URL %>js/osmd/opensheetmusicdisplay.min.js"></script>
</head>
<body>
<div id="xml2">words go here</div>
<div id="app"></div>
</body>
</html>
And this is the JavaScript part I'm attempting to test:
window.onload = function() {
alert("xx == ", document.getElementById("xml2"));
}
alert("xx2 == ", document.getElementById("xml2"));
alert(JSON.stringify(opensheetmusicdisplay, null, 1));
When I run this, they both instances of "xml2" show blanks. The opensheetmusicdisplay does show data, which means it is reading from the source in the head section in index.html
It was pointed out to me in the comments that alert only take one argument. That's a mistake that I'm going to let sit for the moment. The error in the console is TypeError: document.getElementById(...) is null.
Now, this is the main.js. There are a lot of comments because of my various ideas:
// vue imports and config
import Vue from 'vue'
import App from '#/App'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
Vue.config.productionTip = false
// page imports
import Notation from '#/components/Notation'
import HomePage from '#/components/HomePage'
// component imports and registration
import { FoundationCSS } from '#/../node_modules/foundation-sites/dist/css/foundation.min.css'
Vue.component('foundation-css', FoundationCSS)
import SideNav from '#/components/SideNav'
Vue.component('side-nav', SideNav);
// import * as Osmd from '#/../public/js/osmd/opensheetmusicdisplay.min.js'
// Vue.component('osmd-js', Osmd)
// import { OsmdJs } from '#/components/Osmd'
import * as XmlJs from '#/../public/js/osmd/xml-loader.js'
Vue.component('xml-js', XmlJs)
// import XLoad from '#/components/XmlLoader'
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/',
components: {
maininfo: HomePage
}
},
{ path: '/chromatic-scales/c-chromatic-scale',
components: {
maininfo: Notation// ,
// xmlloader: XLoad
}
}
]
})
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
I registered XmlJs as global because this is the only way out of 100 things that actually works. I then embed it in Notation.vue like so:
<template>
<div>
<div id="xml">
{{ notation.data }}
</div>
<xml-js />
</div>
</template>
<script>
import axios from 'axios'
export default ({
data () {
return {
notation: null,
}
},
mounted () {
axios
.get('http://localhost:3000/chromatic-scales/c-chromatic-scale')
.then(result => (this.notation = result))
}})
</script>
<style scoped></style>
The last file is the meat and potatoes of what I'm trying to do. The xml-loader.js slurps the data from <div id="xml"> and does whatever magic the program does in order to render the output I want. The issue is that there doesn't seem to be anyway to wait for the stuff in {{ notation.data }}.
I am new to using vuejs and front-end javascript frameworks in general. I do recognize the code is probably not optimal at this time.
There is race condition where DOM element is not available at the time when it's accessed. The solution is to not access DOM elements created by Vue outside of it. DOM element is ready for use only after asynchronous request:
<template>
<div>
<div ref="xml" id="xml">
{{ notation.data }}
</div>
<xml-js />
</div>
</template>
<script>
import axios from 'axios'
export default ({
data () {
return {
notation: null,
}
},
async mounted () {
const result = await axios
.get('http://localhost:3000/chromatic-scales/c-chromatic-scale')
this.notation = result;
this.$nextTick(); // wait for re-render
renderXml(this.$ref.xml); // pass DOM element to third-party renderer
}})
You can import xml-loader.js into the Notation.vue as a function. Then you can simply do something like this:
mounted () {
axios.get(PATH).then(result => {
this.notation = result
let xmlResult = loadXML(result)
doSomethingWithResult(xmlResult)
}
},
methods: {
doSomethingWithResult (result) {
// do something
}
}

How to use external js files in reactjs

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.

Making site multi language support using google translate for React js

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 />

Categories