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.
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'm currently rewriting a project of mine using ecmascript 2015.
I have a module.js file in which I have two classes. I would like to use those classes in two files (index.php and page.php which is a dynamic generated page included in index.php).
My treefile looks like this:
/..
modules.js // Where I store my classes
page.php // This also contains a <script> part in which I would like to use my classes
index.php // Where I import my .js files
script.js // Where I would also like to use my classes
I have imported my classes in the index.php file like this:
<script type="module" src="js/modules.js">
import * from "./js/modules.js"
</script>
<script src="script.js"></script>
And my module file looks like this:
export { Blabla1 , Blabla2 };
class Blabla1 {
constructor(......) {
.....
}
class Blabla2 {
constructor(......) {
.....
}
}
The problem is that I can't initiate any of the class I've imported in script.js and page.php and get stuck with:
ReferenceError: Blabla1 is not defined
If anyone has any guess on my problem I would really appreciate
Ideally this should work:
<script type="module">
import { Blabla1, Blabla2 } from './js/module.js';
var bla1 = new Blabla1();
</script>`
export { Blabla1 , Blabla2 };
class Blabla1 {
constructor() {
console.log('In Blabla1');
}
} // It's missing
class Blabla2 {
constructor() {
console.log('In Blabla2');
}
}
If you want export/import a class from one.js file to another.js file you should use this code below.
export class Person {
static logme() {
console.log('Hi');
}
}
And then call it from another.js file
import Person from './another.js';
console.log(Person.test());
I have an html file that looks like this:
<!DOCTYPE html>
<html>
<head>
<title>AppName</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
</head>
<body>
<div id="container"></div>
<script src="/bundle.js"></script>
</body>
</html>
And I have a javascript file that contains this:
EDIT: included jQuery via npm, and it seems to have worked.
export function getData(arg, callback) {
var $ = require('jQuery'); // This line was added via EDIT above.
$.ajax({
type: "GET",
url: "/get_data",
data: {data: arg},
success: callback
});
}
When I go to my page and execute the function, I eventually get this error:
Uncaught ReferenceError: $ is not defined
at Object.getData (http://localhost:1234/static/bundle.js:21665:6)
Based on the questions/answers I've seen on SOF, it seems like the solution was to include the jquery script in my html file.
Any ideas what I might be doing wrong?
EDIT: As per request, here is my react index.js file. The error is coming from within the searchApi.js file:
import React from 'react';
import ReactDOM from 'react-dom';
import SearchBar from './components/SearchBar';
import * as searchApi from './api/searchApi';
class App extends React.Component {
constructor() {
super();
this.getData = this.getData.bind(this);
this.processData = this.processData.bind(this);
}
getData(data) {
searchApi.getData(data, this.processData);
}
processData(payload) {
console.log(payload);
}
render() {
return (
<div>
<SearchBar getData={this.getData}/>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('container')
);
I am using global script declaration inside index.html
<!DOCTYPE html>
<html>
<head>
<script src='https://js.espago.com/espago-1.1.js' type='text/javascript'></script>
...
</head>
<body>
...
</body>
Now I want to use it inside the component.
import * as React from "react";
import * as $ from "jquery";
//how to import Espago?
export default class EspagoPayment extends React.Component<any, any> {
componentDidMount() {
$("#espago_form").submit(function(event){
var espago = new Espago({public_key: 'xxx', custom: true, live: false, api_version: '3'});
espago.create_token({
...
});
});
}
render() {
return (
...
);
}
}
Webpack gives an error on build.
error TS2304: Cannot find name 'Espago'
How to get Espago visible inside the component?
Maybe there is other way to link to online js resource?
You have to tell TypeScript that it's defined somewhere else.
declare var Espago: any;
See https://stackoverflow.com/a/13252853/227299