How to run regular JavaScript in React/Preact application - javascript

I am trying to use masonry in a Preact app, tried several React plugins using react/compat but they are all failing.
This is how I'm trying:
const App = () => (
<Landing name="shoecare">
<!-- all the working code -->
<!-- here -->
<script src="https://unpkg.com/masonry-layout#4.2.2/dist/masonry.pkgd.min.js"></script>
<script>
var grid = document.querySelector(".how__list");
new Masonry(grid, {
itemSelector: ".how__item",
columnWidth: document.querySelctor('body').clientWidth / 2 - 16,
});
</script>
<!-- end -->
</Landing>
);
clab(<App />);
But it fails to compile:
Is it posible?
I managed to run some regular JS onclick, like so;
<span class="services__nav-previous" onClick={(e) => scrollLeft()}>

i guess you're using functional components, so to have any js code inside of them you should do it like this
const App = () => {
// your js code here
return (
// here you put your components
)
}
EDIT: and you don't put < script >< /script > inside of your functional component, you add them in your index.html file, not in app.js

Related

How to import js file from url and initialize a class in React?

I want to embed PitchPrint app on a React website. They have a vanilla html/js integration tutorial here. I added script tags with links to jQuery and their app file in my index.html file, as they require and then created a separate jsx file that suposed to return a button witch opens the app. The problem is, when I try to build, it throws an error 'PitchPrintClient' is not defined witch suposed to come from their files.
My index.html file:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://pitchprint.io/rsc/js/client.js"></script>
<title>App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
My jsx file:
import React from 'react';
const AppButton = () => {
let _launchButton = document.getElementById('launch_btn');
let _previewDiv = document.getElementById('pp_preview_div');
let _loaderDiv = document.getElementById('pp_loader_div');
_launchButton.setAttribute('disabled', 'disabled');
var ppclient = new PitchPrintClient({
apiKey: 'f80b84b4eb5cc81a140cb90f52e824f6', //Kinldy provide your own APIKey
designId: '3d8f3899904ef2392795c681091600d0', //Change this to your designId
custom: true
});
//Function to run once the app is validated (ready to be used)
var appValidated = () => {
_launchButton.removeAttribute('disabled'); //Enable the Launch button
_launchButton.onclick = () => ppclient.showApp(); //Attach event listener to the button when clicked to show the app
_loaderDiv.style.display = 'none'; //Hide the loader
};
//Function to run once the user has saved their project
var projectSaved = (_val) => {
let _data = _val.data; //You can console.log the _data varaible to see all that's passed down
if (_data && _data.previews && _data.previews.length) {
_previewDiv.innerHTML = _data.previews.reduce((_str, _prev) => `${_str}<img src="${_prev}">`, ''); //Show the preview images
}
};
ppclient.on('app-validated', appValidated);
ppclient.on('project-saved', projectSaved);
return <div>
<div id="pp_loader_div"><img src="https://pitchprint.io/rsc/images/loaders/spinner_new.svg" /></div>
<button id="launch_btn" >Launch Designer</button>
<div id="pp_preview_div"></div>
</div>;
};
export default AppButton;
PS: I know getElementById does not realy work with react, I'll deal with that later, for now I just want to initialize this app.
that's because the component is not mounted yet.
you need to call document.getElementById once the component is mounted, and in order to access dom elements inside the component you need to call it inside useEffect hook
useEffect(() => {
let _launchButton = document.getElementById("launch_btn");
let _previewDiv = document.getElementById("pp_preview_div");
let _loaderDiv = document.getElementById("pp_loader_div");
_launchButton.setAttribute("disabled", "disabled");
var ppclient = new PitchPrintClient({
apiKey: "f80b84b4eb5cc81a140cb90f52e824f6", //Kinldy provide your own APIKey
designId: "3d8f3899904ef2392795c681091600d0", //Change this to your designId
custom: true,
});
//Function to run once the app is validated (ready to be used)
var appValidated = () => {
_launchButton.removeAttribute("disabled"); //Enable the Launch button
_launchButton.onclick = () => ppclient.showApp(); //Attach event listener to the button when clicked to show the app
_loaderDiv.style.display = "none"; //Hide the loader
};
//Function to run once the user has saved their project
var projectSaved = (_val) => {
let _data = _val.data; //You can console.log the _data varaible to see all that's passed down
if (_data && _data.previews && _data.previews.length) {
_previewDiv.innerHTML = _data.previews.reduce(
(_str, _prev) => `${_str}<img src="${_prev}">`,
""
); //Show the preview images
}
};
ppclient.on("app-validated", appValidated);
ppclient.on("project-saved", projectSaved);
}, []);
Read more about React hooks and their constraints.
https://reactjs.org/docs/hooks-intro.html
also make sure to access global variables using window.PitchPrintClient
also, make sure your app is mounted once the dom is ready. by moving your script tags to the end of the body tag or using jquery on ready callback.
PS: The answer is not considering the best practices of writing react components, but I encourage you to use refs and minimize accessing to dom as much as you could.

Using JavaScript in Angular 12

I'm learning to use Angular 12 and trying to build a sidenav. I know I can use angular material, but I don't want to use the css associated with it.
I'd like to use this in my project. But can't understand how to convert the JS to be used in the angular 12 project.
I've placed the javascript in a menu.js under my assets/js folder. But can't understand how it's used with the component.js since it isn't a actual function, but a document.queryselectorall.
let arrow = document.querySelectorAll(".arrow");
for (var i = 0; i < arrow.length; i++) {
arrow[i].addEventListener("click", (e)=>{
let arrowParent = e.target.parentElement.parentElement; //selecting main parent of arrow
arrowParent.classList.toggle("showMenu");
});
}
let sidebar = document.querySelector(".sidebar");
let sidebarBtn = document.querySelector(".bx-menu");
console.log(sidebarBtn);
sidebarBtn.addEventListener("click", ()=>{
sidebar.classList.toggle("close");
});
Your code is old school. You need to get used to the Angular approach.
Basically what your code is doing is toggling a CSS class on an element on click. Here's how you do that in Angular:
In your HTML file:
<button (click)="toggleSidebar()">Toggle Sidebar</button>
<!-- the show-me class is added when showSidebar is true -->
<div class="sidebar" [class.show-me]="showSidebar">I am a sidebar</div>
In your .ts file:
showSidebar = false;
toggleSidebar() {
this.showSidebar = !this.showSidebar;
}
And then add your animation styles in your .styles file:
.sidebar {
// styles
}
.sidebar.show-me {
// styles
}

Can't get Google Ads to show in React no matter what I do

I've been following this example:
https://www.jamesbaum.co.uk/blether/using-google-adsense-with-react/
I have this component:
import React from "react";
export default class AdBanner extends React.Component {
componentDidMount () {
(window.adsbygoogle = window.adsbygoogle || []).push({});
}
render () {
return (
<div className='ad'>
<ins className='adsbygoogle'
style={{ display: 'block' }}
data-ad-client='div-gpt-ad-1536172937182-0'
data-ad-slot='/164808479/Leaderboard'
data-ad-format='auto' />
</div>
);
}
}
I have this on my index.html:
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
When I run my test page I get no ads rendering and this error:
I have no idea what this error means or how to resolve it.
It's critical to mention that the client and slot IDs work perfectly in a non-react test app So something else must be wrong here.
also, I am testing this via localhost:8080 -- which works for the non react test app, so I do not think it's a localhost/google ads issue.
IN OUR OLD NON-REACT APP
in our <header>:
<script async='async' src='https://www.googletagservices.com/tag/js/gpt.js'></script>
<script>
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
</script>
<script>
googletag.cmd.push(function() {
googletag.defineSlot('/164808479/Leaderboard', [728, 90], 'div-gpt-ad-1536172937182-0').addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.enableServices();
});
</script>
in our <page.php>:
<!-- /164808479/Leaderboard -->
<div id='div-gpt-ad-1536172937182-0' style='height:90px; width:728px;'>
<script>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1536172937182-0'); });
</script>
</div>
This produces a working ad right now, even from 127.0.0.1:80 (running via Docker) Our problem is our lack of ability to make this work inside a React component.
You are getting HTTP 400 (i.e. Bad Request) because the data being sent to google ad servers seems wrong.
The data-ad-client value should have the format like ca-pub-00000000000000 which is obtained from adsense administration page. (I believe this is not your case!!!)
The data you provide, div-gpt-ad seems as an id of a divfor google publisher tag which has the id /164808479/Leaderboard. So in order to use that in your react application properly you can use this library: https://github.com/nfl/react-gpt
So below you can find the modified code which is suitable for your case. Just add react-gptto your react application.
import React from "react";
import {Bling as GPT} from "react-gpt";
GPT.enableSingleRequest();
export default class AdBanner extends React.Component {
render () {
return (
<div id="div-gpt-ad-1536172937182-0">
<GPT
adUnitPath="/164808479/Leaderboard"
slotSize={[728, 90]}
/>
</div>
);
}
}
You can see the above code working beautifully in this link: https://codesandbox.io/embed/determined-bash-k30nq
Just for these who are reading between lines (as me) - put push call to useEffect instead of row jsx like:
useEffect(() => {
window.adsbygoogle = window.adsbygoogle || [];
window.adsbygoogle.push({});
}, [])
You just need to wait, when you first implement Adsense it will give this error. It took until next morning for Adsense to start displaying ads. I implemented their Responsive ad type.
c/o https://stackoverflow.com/a/38351709/109941

How to write regular javascript and load online external library in vue.js components?

I'm creating a website with vue.Js (vue.cli) to show some of my work.
Actually all the interactions and experiments are made in a iframe, because I don't understand how to load and use external javascript
For example in one of my components I would like to use gio.js.
To use it you need to call 4 libraries:
jquery -> https://code.jquery.com/jquery-3.3.1.slim.min.js
three.js -> https://threejs.org/build/three.min.js
gio.js -> https://raw.githack.com/syt123450/giojs/master/build/gio.min.js
data -> https://raw.githack.com/syt123450/giojs/master/assets/data/sampleData.js
So actually I write that in my component, but nothing works:
So, I would like to proper load external js files, and write regular js in my components or in an externals files.
<template>
<div class="planet">
//globalArea is for render the planisphere
<div id="globalArea"></div>
</div>
</template>
<script>
export default {
mounted() {
let jqueryScript = document.createElement('script')
jqueryScript.setAttribute('src', 'https://code.jquery.com/jquery-3.3.1.slim.min.js')
document.head.appendChild(jqueryScript);
let threeScript = document.createElement('script')
threeScript.setAttribute('src', 'https://threejs.org/build/three.min.js')
document.head.appendChild(threeScript);
let gioScript = document.createElement('script')
gioScript.setAttribute('src', 'https://raw.githack.com/syt123450/giojs/master/build/gio.min.js')
document.head.appendChild(gioScript);
let dataScript = document.createElement('script')
dataScript.setAttribute('src', 'https://raw.githack.com/syt123450/giojs/master/assets/data/sampleData.js"')
document.head.appendChild(dataScript);
}
methods: {
// Get the container to hold the IO globe
var container = document.getElementById( "globalArea" );
// Create Gio.controller
var controller = new GIO.Controller( container );
// Add data
controller.addData( data );
// Initialize and render the globe
controller.init();
}
}
</script>
You have a common error, the methods properties is an object that carries all the methods you want to define for example:
export default {
methods: {
myFirstMethod () {
//code goes here
},
mySecondMethod () {
//code goes here
},
}
}
If you want to initialize your data when the component is shown you can load the scripts on the beforeCreate hook and paste your code on the mounted hook. Here is how it should look:
var app = new Vue({
el: '#app',
beforeCreate() {
let jqueryScript = document.createElement('script')
jqueryScript.setAttribute('src', '//code.jquery.com/jquery-3.3.1.slim.min.js')
document.head.appendChild(jqueryScript);
let threeScript = document.createElement('script')
threeScript.setAttribute('src', '//threejs.org/build/three.min.js')
document.head.appendChild(threeScript);
let gioScript = document.createElement('script')
gioScript.setAttribute('src', '//raw.githack.com/syt123450/giojs/master/build/gio.min.js')
document.head.appendChild(gioScript);
let dataScript = document.createElement('script')
dataScript.setAttribute('src', '//raw.githack.com/syt123450/giojs/master/assets/data/sampleData.js')
document.head.appendChild(dataScript);
},
mounted() {
setTimeout(() => {
// Get the container to hold the IO globe
var container = document.getElementById( "globalArea" );
// Create Gio.controller
var controller = new GIO.Controller( container );
// Add data
controller.addData( data );
// Initialize and render the globe
controller.init();
}, 2000)
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="planet">
//globalArea is for render the planisphere
<div id="globalArea" style="height: 500px"></div>
</div>
</div>
Also keep in mind that you can only access those scripts when they are fully loaded, that's why I'm using a setTimeout with 2 seconds of delay.

Initialize materializecss component in React

I'm trying to add the Carousel image slider from MaterializeCSS to a simple React component but i'm not able to initialize it! It would be very helpful to know where i should do it in my code
import React, { Component } from 'react';
import { M } from 'materialize-css/dist/js/materialize.min.js';
export default class Slider extends Component {
componentDidMount() {
var elem = document.querySelector('.carousel');
var instance = M.Carousel.init(elem, { duration: 200 });
}
render() {
return (
<div className="container center-align">
<h1 className="header pink-text">Slider</h1>
<div className="carousel">
<a className="carousel-item" href="#one!">
<img src="https://www.w3schools.com/images/picture.jpg" />
</a>
<a className="carousel-item" href="#two!">
<img src="../../public/images/lana/1.jpg" />
</a>
<a className="carousel-item" href="#three!">
<img src="../../public/images/lana/1.jpg" />
</a>
<a className="carousel-item" href="#four!">
<img src="../../public/images/lana/1.jpg" />
</a>
<a className="carousel-item" href="#five!">
<img src="../../public/images/lana/1.jpg" />
</a>
</div>
</div>
);
}
}
this gives me an Error:
Cannot read property 'Carousel' of undefined
i tried to do it with Jquery, no errors but didn't work!
I had the same issue.
Solved it by adding the materializecss npm module
npm install materialize-css
and then importing it into the component
import M from "materialize-css";
and in the componentDidUpdate method, added the init
componentDidUpdate() {
let collapsible = document.querySelectorAll(".collapsible");
M.Collapsible.init(collapsible, {});
}
Problem solved!!
Using React Hook with useEffect you can also initialize each feature on Materialize, for example:
import React, { useEffect, Fragment } from "react";
import M from "materialize-css/dist/js/materialize.min.js";
useEffect(() => {
// Init Tabs Materialize JS
let tabs = document.querySelectorAll(".tabs");
M.Tabs.init(tabs);
});
In my case, I used tabs to initialize the Materialize feature.
Looks like you're using a .min file to import M from. You should install MaterializeCSS as a node module instead. You're getting an error because M is not defined as anything. There aren't any exports from that .min file.
If you want to wait until the script has loaded it is better to do that with a callback instead of setTimeout.
function loadScript(url, callback) {
var script = document.createElement("script")
script.type = "text/javascript";
if (callback) {
script.onload = callback;
}
document.body.appendChild(script)
script.src = url;
}
loadScript(pathtoscript, function() {
alert('script ready!');
});
If you want to use min.js file in your application, try adding it in html file using tag.
Alternatively try adding node modules using npm package.
Hope this helps.
I figured out that it needs some time to render the content. When I use setTimeout() function and call that initialization JS lines it worked.
I initialize the Carousel js code from the main html page with setTimeout() function, i used a spinner to make look little better
it looks like this
<script>
setTimeout(() => {
var elem = document.querySelector('.carousel');
var instance = M.Carousel.init(elem, {});
if (document.querySelector('.photos').classList) {
document.querySelector('.photos').classList.remove("spinner")
}
}, 2000)
</script>
add window.M. ...
useEffect(() => {
var elem = document.querySelector(".carousel");
var instance = window.M.Carousel.init(elem, {
fullWidth: true,
indicators: true,
});
});

Categories

Resources