React: Using document.QuerySelector as part of a library - javascript

I am trying to use an image hover effect library in React. Here is the library. The library uses Three.js and GSAP to animate images. I've built a small example project with this library in a vanilla JS file.
I was able to build it easily like this. Here is my HTML file:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="./styles.css"/>
<title></title>
</head>
<body>
<div class="container">
<div class="distortion">
</div>
<div class="distortion2">
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js" integrity="sha256-lPE3wjN2a7ABWHbGz7+MKBJaykyzqCbU96BJWjio86U=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/108/three.min.js" integrity="sha256-3mBEX8I0uMLF7+AUjJeTCelosuorzYpqwBMBPDTyQqY=" crossorigin="anonymous"></script>
<script src="./hover.js"></script>
<script src="./app.js"></script>
</body>
</html>
And here is my JS file:
new hoverEffect({
parent: document.querySelector(".distortion"),
intensity: 1,
image1: "./images/kaapo.jpg",
image2: "./images/kakko-rangers.jpg",
displacementImage: "./images/ladyliberty3.png"
});
new hoverEffect({
parent: document.querySelector(".distortion2"),
intensity: 1,
image1: "./images/jack.jpg",
image2: "./images/hughes-card.jpg",
displacementImage: "./images/devils-40.png"
});
Everything works, but now I'm trying to do something similar in a React project and I'm having trouble using this library in React.
Here is what I've tried:
import React, { Component } from 'react';
import hoverEffect from 'hover-effect';
import kakko from '../assets/kaapo.jpg';
import {kakkoRangers} from '../assets/kakko-rangers.jpg';
import {ladyLiberty} from '../assets/ladyliberty3.png';
import styled, { css } from 'styled-components';
const STYLES = styled.div`
height: 100vh;
width: 100%;
.my-div {
height: 20em;
width: 30em;
}
`;
class Test extends Component {
constructor(props) {
super(props);
this.state = {
}
}
componentDidMount = () => {
}
render() {
const animation = new hoverEffect({
parent: document.querySelector('.my-div'),
intensity: 0.3,
image1: {kakko},
image2: {kakkoRangers},
displacementImage: {ladyLiberty}
});
return (
<STYLES>
<div>
<h1>Test</h1>
<div className="my-div">
</div>
</div>
</STYLES>
);
}
}
export default Test;
I don't think document.querySelector('.my-div') is working in my animation variable. Do querySelectors not work in React? How can I properly select the div?
How could I implement this in React? I tried nesting the animation variable in componentDidMount but that didn't work either.

Usually when you want to directly access DOM elements in React you use the ref keyword:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}
More at the React documentation.

Related

How to use vue3-sfc-loader with scss

does anyone know how i would use vue3-sfc-loader, which lets me use vue without build tools, while still being able to use scss styling?
The following example is taken from here:
Index.html
<!DOCTYPE html>
<html>
<head>
<script type="importmap">
{
"imports": {
"vue": "https://jspm.dev/vue/dist/vue.js"
}
}
</script>
</head>
<body style=margin:0>
<div id="container"></div>
<script type="module">
import Vue from 'vue';
container.innerHTML = '<p>{{ message }}</p>';
new Vue({
el: '#container',
data() {
return {
message: 'Hello Vue.js!'
}
}
});
</script>
</body>
</html>
myComponent.vue
<template>
<span class="example">{{ msg }}</span>
</template>
<script>
export default {
data () {
return {
msg: 'world!',
color: 'blue',
}
}
}
</script>
<style scoped>
.example {
color: v-bind('color');
}
</style>
I want to use this for a small project. Thank you very much in advance!

ReactDOM.render rendering page

New to ReactJS,
Can not find out why this page is not showing anything -
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="react.16.8.6.development.js"></script>
<script src="react-dom.16.8.6.development.js"></script>
<script src="babel.7.5.4.min.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
class MyClass extends React.Componet{
render() {
return(<h1>Hello React Componets!</h1>);
}
}
ReactDOM.render(
<h1>MyClass</h1>,
document.getElementById('container')
);
</script>
</body>
</html>
I am getting error in console -
VM43:19 Uncaught TypeError: Super expression must either be null or a function at _inherits (:19:113)
at :26:3
at :42:2
Try these code:
<script type="text/babel">
class MyClass extends React.Component{
render() {
return(<h1>Hello React Componets!</h1>);
}
}
ReactDOM.render(
<h1><MyClass/></h1>,
document.getElementById('container')
);
</script>
Your problem is here,
<h1>MyClass</h1>, //This is not a react component, this will only print `MyClass` as text on page
Just change,
ReactDOM.render(
<h1>MyClass</h1>,
document.getElementById('container')
);
to this,
ReactDOM.render(
<MyClass />,
document.getElementById('container')
);
Note: Correct the typo in your code,
class MyClass extends React.Componet should be class MyClass extends React.Component{
Demo

Is it possible to use a React component from within an HTML file?

What I want to do is have a video with a set of controls below it. There are many places where I will need these controls, so I have decided to use React to render them so they are easily reusable.
Here is my code:
import React from 'react';
import ReactDOM from 'react-dom';
import './styles.css';
class VideoControls extends React.Component {
render() {
return(
<div>TESTING</div>
);
}
}
ReactDOM.render(
<VideoControls />,
document.getElementById('controls')
);
/* code for tags */
html, body {
height: 100%;
}
html {
background-color: rgb(48, 48, 48);
}
body {
padding: 16px;
/* overrides default w3.css */
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
}
video {
display: block;
}
/* specialised code for other elements */
.video-panel, .video-panel-second {
background-color: rgb(75, 75, 75);
color: rgb(185, 185, 185);
height: 45%;
width: calc(50% - 11px);
display: inline-block;
text-align: center;
}
.video-panel-second {
margin-left: 16px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="styles.css"/>
<link rel="stylesheet" href="w3.css"/>
<script src="https://unpkg.com/react#16/umd/react.production.min.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.production.min.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone#6.26.0/babel.min.js" type="text/babel"></script>
<title>Editor UI Demo</title>
</head>
<body>
<div class="video-panel w3-container w3-padding-24 w3-round">
<video id="source-video" src="/css-vse/assets/PostingLetter.MOV" height="100%" width="100%">Video not displayed.</video>
<div id="controls"></div>
</div>
<div class="video-panel-second w3-container w3-padding-24 w3-round">
<video id="timeline-video" src="/css-vse/assets/Walking.MOV" height="100%" width="100%">Video not displayed.</video>
<div id="controls"></div>
</div>
<script src="index.js"></script>
</body>
</html>
I want to render a <VideoControls> within div#controls but I keep getting an "Uncaught SyntaxError: Unexpected Identifier" when trying to do so. Is it possible to use the <VideoControls> React component from within my HTML file, or do I have to make the entire page a React app?
Thank you for your time.
Instead of using id to render the Component, use a class. Get the elements with the class name and in a loop render your react component.
Follow this answer I found on StackOverFlow, will help you sort this out.
Working Example.
<!-- Index.html -->
<div id="app">
INSIDE APP DIV
<div class="here">
</div>
<div class="here">
</div>
</div>
And the React Component
class VideoControls extends React.Component {
render() {
return (
<div>My VideoControls</div>
)
}
}
// getting all the divs with class here
let myContainerLength = document.getElementsByClassName("here").length;
if (myContainerLength > 0) {
// if there are more than one instances of element with the class `here`
// loop through the elements with class `here` using and index `i`
for (let i=0; i<myContainerLength; i++) {
ReactDOM.render(<VideoControls />, document.getElementsByClassName("here")[i]);
}
}
Working example: JSFiddle

Checkox binding in ReactJS

I am trying to create a simple checkbox using reactJS and trying to bind the state of the checkbox using handlecheck()
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone#6.15.0/babel.min.js"></script>
<title>Getting Started with React</title>
</head>
<body>
<div id='react-container'></div>
<script type="text/babel">
class Checkbox extends React.Component{
constructor(props){
super(props)
this.state = {
checked: false
}
this.handleCheck = this.handleCheck.bind(this)
}
handleCheck(){
this.setState ({
checked: true
})
}
render(){
return(
<div>
<input type = "checkbox"/>
</div>
)
}
}
ReactDOM.render(
<Checkbox />,
document.getElementById("react-container")
)
</script>
</body>
</html>
But, here even though I am using
handleCheck(){
this.setState ({
checked: true
})
}
I am still able to check and uncheck the box multiple time, but in reality, it shouldn't as it has to check it once and should stop.
I know that in the actual scenario it should be something like:
handleCheck(){
this.setState ({
checked: !this.state.checked
})
}
Can someone tell me why am I able to check and uncheck multiple times even though I am doing it wrong?
You are create a controlled component, which need a handler to change the state, and it's value/checked properties are controlled by the state.
You need to assign this.handleCheck as the onChange handler, and this.state.checked as the checked property value:
class Checkbox extends React.Component {
constructor(props) {
super(props)
this.state = {
checked: false
}
this.handleCheck = this.handleCheck.bind(this)
}
handleCheck() {
this.setState({
checked: true
})
}
render() {
return (
<div>
<input
type="checkbox"
checked={this.state.checked}
onChange={this.handleCheck}
/>
</div>
)
}
}
ReactDOM.render(
<Checkbox /> ,
document.getElementById("react-container")
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='react-container'></div>
You forgot to add handleCheck to your checkbox
<div>
<input type = "checkbox" onChange={this.handleCheck} checked={this.state.checked}/>
</div>

Passing data returned from function to polymer custom element

I'm starting with Polymer 3 and I'm facing an issue I cannot solv.
I have a custom element which will show a play card; its only property is an object with its suit and number. The element is more or less like this:
import {html, PolymerElement} from '#polymer/polymer/polymer-element.js';
class CardElement extends PolymerElement {
static get template() {
return html`
<style>
:host {
display: block;
}
</style>
`;
}
static get properties() {
return {
card: {
type: Object,
value: () => {
return {
suit: 'hearts',
figure: 'king'
}
}
},
};
}
ready() {
super.ready();
console.log(this.card.figure);
}
}
window.customElements.define('card-element', CardElement);
Next I want to check that every thing is working with and HTML file.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
<title>card-element demo</title>
<script src="../node_modules/#webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
<script type="module">
import '#polymer/iron-demo-helpers/demo-pages-shared-styles';
import '#polymer/iron-demo-helpers/demo-snippet';
</script>
<script type="module" src="../card-element.js"></script>
<custom-style>
<style is="custom-style" include="demo-pages-shared-styles">
</style>
</custom-style>
</head>
<body>
<div class="vertical-section-container centered">
<h3>Basic card-element demo</h3>
<demo-snippet>
<template>
<card-element card='{"suit" "hearts", "figure" "1"}'></card-element>
</template>
</demo-snippet>
</div>
</body>
</html>
Console.log in ready method shows that data is binded but, whenever I try to pass a json data returned from a function, the console.log show "undefined".
<body>
<div class="vertical-section-container centered">
<h3>Basic card-element demo</h3>
<demo-snippet>
<template>
<card-element card="{{_getCard}}"></card-element>
</template>
</demo-snippet>
</div>
<script>
function _getCard() {
return JSON.stringify({
"suit": "clubs",
"figure":"1"
});
}
</script>
</body>
I checked loading data returned into a variable and binding the variable to the custom element but still didn't work.
How should I pass the data to the custom element?
Thanks for your answers.
Try this:
<script>
function _getCard() {
let data = {
"suit": "clubs",
"figure":"1"
};
return data;
}
</script>

Categories