Turning Vanilla Javascript into React app in Components - javascript

I'm Turning this Sign in/up Form into a react application, I'm building it through the use of components. I am new to react so I need some help turning vanilla scripts into react components.
Can someone help me code the vanilla js into components (with sliding transition) ?
Vanilla Javascript
const signUpButton = document.getElementById('signUp');
const signInButton = document.getElementById('signIn');
const container = document.getElementById('container');
signUpButton.addEventListener('click', () => {
container.classList.add("right-panel-active");
});
signInButton.addEventListener('click', () => {
container.classList.remove("right-panel-active");
});
and React Component:
export const SignForms = () => {
const [ containerActive, setContainerActive] = useState(false);
const signUpButton = () => {
setContainerActive(false);
};
const signInButton = () => {
setContainerActive(true);
};
.....
<div className="overlay-container">
<div className="overlay">
<div className="overlay-panel overlay-left">
<div className={containerActive ? " right-panel-active" : ""}></div>
<h1 className="font-effect-3d">Come On!</h1>
<p className="font-effect-emboss">Start Your Journey With Us</p>
<button className="ghost" onClick={signInButton} id="signIn" >Sign In</button>
</div>
<div className="overlay-panel overlay-right">
<h1 className="font-effect-3d">No Account?</h1>
<p className="font-effect-emboss">No Problem! Just Sign Up Here</p>
<button className="ghost " onClick={signUpButton} id="signUp">Sign Up</button>
</div>
</div>
</div>
JsFiddle for Vanilla : https://jsfiddle.net/barrogocarlo/dyg9mqn2/ ||
Git Repo for React app: https://gitlab.com/carlobarrogo/sample-forms

You were pretty much there. Keep up !!
Following is the working code, i was able reproduce on my sandbox.
https://codesandbox.io/s/github/devpandya/SamplSignIns/tree/main/?file=/src/SignForms.js
I found 2 issues:
The App.css in vanila.js was different then in your React Code. just copy it from your Vanila Code
use containerActive state to maniplulate classes in container div.
const signUpButton = () => {
setContainerActive(true);
};
const signInButton = () => {
setContainerActive(false);
};
return (
<div className="signForms">
<div
className={`container ${containerActive && "right-panel-active"}`}
id="container"
>
Thats it.. !!!..
Also there was a extra div added in your overlay, just remove it, no use of it
<div className="overlay-panel overlay-left">
**<div className={containerActive ? " right-panel-active" : ""}></div>**
<h1 className="font-effect-3d">Come On!</h1>

Related

Div id is not defined in a function using react.js

import React from "react";
import "./profile.css";
const Notifications = () => {
function changeText() {
themebox.textContent =
"Nice";
}
function changeText2() {
themebox.textContent =
"Fair";
}
function changeText3() {
themebox.textContent = "Aggressive";
}
function changeText4() {
themebox.textContent =
"Threatening";
}
return (
<div className="notification-container">
<h3>Notifications</h3>
<div className="notif-picker">
<p className="Selected" onClick={changeText}>
Nice😘
</p>
<p onClick={changeText2}>Fair🕊</p>
<p onClick={changeText3}> Aggressive😈</p>
<p onClick={changeText4}>Threatening🤬</p>
</div>
<div className="theme-show-box">
<div className="theme-box" id="themebox"></div>
</div>
</div>
);
};
export default Notifications;
When i click on one of p tags it shows the text that i put in a function which is displayed in the div with classname "theme-box" and id "themebox". Everything seems to work fine, but i get an error in react saying themebox is not defined. Any idea how i can solve that error? :)
There's no variable named themebox in your javascript. Try this out instead, using react to manage state and functions to change the state on click.
// Get a hook function
const {useState} = React;
const Notifications = () => {
const [displayedText, setDisplayedText] = useState("");
const niceText = () => setDisplayedText("Nice");
const fairText = () => setDisplayedText("Fair");
const aggressiveText = () => setDisplayedText("Aggressive");
const threateningText = () => setDisplayedText("Threatening");
return (
<div className="notification-container">
<h3>Notifications</h3>
<div className="notif-picker">
<p className="Selected" onClick={niceText}>
Nice😘
</p>
<p onClick={fairText}>Fair🕊</p>
<p onClick={aggressiveText}> Aggressive😈</p>
<p onClick={threateningText}>Threatening🤬</p>
</div>
<div className="theme-show-box">
<div className="theme-box" id="themebox">{displayedText}</div>
</div>
</div>
);
};
// Render it
ReactDOM.createRoot(
document.getElementById("root")
).render(
<Notifications />
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
React has it's own way of updating the DOM so it's generally a bad idea to try and manipulate the DOM directly. You should be using and updating state, and then using that state in the JSX.
By doing this you only really need one function which destructures the text content from the clicked element, and sets the state with that text. When the state changes that changed value is reflected in the JSX.
The (new) React documentation site has a good rundown on "how to think in React".
const { useState } = React;
function Example() {
// Initialise the state to an empty string
const [ text, setText ] = useState('');
// When any of the paragraphs is clicked
// destructure the textContent from that element
// and then set the state's new value. `e` is the
// event, and `target` is the element that fired the
// event ie. a paragraph element
function handleClick(e) {
const { textContent } = e.target;
setText(textContent);
}
return (
<div className="notification-container">
<h3>Notifications</h3>
<div className="notif-picker">
<p onClick={handleClick}>Nice 😘</p>
<p onClick={handleClick}>Fair 🕊</p>
<p onClick={handleClick}>Aggressive 😈</p>
<p onClick={handleClick}>Threatening 🤬</p>
</div>
<div className="theme-show-box">
<div className="theme-box">{text}</div>
</div>
</div>
);
}
ReactDOM.render(
<Example />,
document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Dynamically generated cards with JS

I'm trying to make a some dynamically generated bootstrap cards with a button clearing the page and showing the info (which I have stored on a Firebase project). I managed to make the cards show properly but I'm blocked and can't find a way to make each button show a different information.
So basically I have this:
Cards
Content showing
It has to be something close to the eventListener or another way to write the code... I think the way I did it is why its showing all the information on the same card, but how can I write the code right? I'm trying for 2 days and can't work around it.
OBS: I know my code can be a little messy or could be best ways to do some stuff but I'm still learning.
import { getWikiTI } from './prevenirWiki.js'
const dataCard = document.getElementById('data');
async function loadData() {
let i = 0;
const data = await getWikiTI()
dataCard.innerHTML = data.map(d => `
<div class="card border-primary mb-3 fb-item" style="max-width: 20rem;">
<div class="card-header">${d.setor}</div>
<div class="card-body">
<h4 class="card-title">${d.descricao}</h4>
<button type="button" class="btn btn-lg btn-primary fb-item" id="carregar-card">Carregar</button>
</div>
</div>
`,
console.log(data),
console.log(i)
).join('')
const btnCarregar = document.getElementById('carregar-card')
btnCarregar.addEventListener('click', () => {
dataCard.innerHTML = data.map(function (d) {
return `${d.conteudo}`;
})
document.body.appendChild(dataCard)
})
}
document.onload = loadData();
EDIT: Alright ! I managed to get it working... not the best code in the world but it's something :) If anyone has any opinions or ideias on how to improve it, im all ears.
import { getWikiTI } from './prevenirWiki.js'
const dataCard = document.getElementById('data');
async function loadData() {
let i = 0;
const data = await getWikiTI()
dataCard.innerHTML = data.map(d => `
<div class="card border-primary mb-3 fb-item" style="max-width: 20rem;">
<div class="card-header">${d.setor}</div>
<div class="card-body">
<h4 class="card-title">${d.descricao}</h4>
<button type="button" class="btn btn-lg btn-primary fb-item" id="carregar-card${i++}">Carregar</button>
<p hidden class="card-text">${d.conteudo}</p>
</div>
</div>
`,
).join('')
for (let i = 0; i <= data.length; i++) {
let btnCarregar = document.getElementById(`carregar-card${i}`)
btnCarregar.addEventListener('click', () => {
dataCard.innerHTML = data[i].conteudo;
document.body.appendChild(dataCard)
})
}
}
document.onload = loadData();

Multiple Rotating Title Script

I have a HTML/CSS/JS script that is allowing me to rotate text for a certain part of it. I'm just having the problem of making it work for multiple sections as the script targets a span[data-up] & span[data-show].
Any help appreciated, code shown below.
<section class="rotating-text-section">
<h2>
We educate by
<div class="wrapper">
<span data-up>teaching.</span>
<span data-show>showing.</span>
<span>doing.</span>
<span>repeating.</span>
</div>
</h2>
</section>
setInterval(() => {
const up = document.querySelector('span[data-up]');
const show = document.querySelector('span[data-show]');
const down = show.nextElementSibling || document.querySelector('span:first-child');
up.removeAttribute('data-up');
show.removeAttribute('data-show');
show.setAttribute('data-up', '');
down.setAttribute('data-show', '');
}, 2000);
I just changed the class names of each span element and targeted them by this in the JavaScript script.
My second snippet of HTML was:
<div class="wrapper-two">
<span class="second-span" data-up>technology.</span>
<span class="second-span" data-show>experience.</span>
<span class="second-span">listening.</span>
<span class="second-span">experimenting.</span>
</div>
My second JS script is as follows:
setInterval(() => {
const up = document.querySelector('.second-span[data-up]');
const show = document.querySelector('.second-span[data-show]');
const down = show.nextElementSibling ||
document.querySelector('.second-span:first-child');
up.removeAttribute('data-up');
show.removeAttribute('data-show');
show.setAttribute('data-up', '');
down.setAttribute('data-show', '');
}, 1000);

How to render conditional with classNames with Reactjs

I am trying to use classNames to replace the conditional below in one line.
My problem is that i am not sure what is the right way to write the code because of the div etc...
I have the codes below :
conditional
const { pageTitle, removeTitle = false } = props; # destructuring
let result;
if(removeTitle){
result = <div className="header-without-title">{pageTitle}</div>;
} else {
result = <div className="header-with-title">{pageTitle}</div>;
}
return (<div className="result-title">{result});
};
If the div did not exist, i could write something like this...
const result = classNames({"header-without-title": removeTitle, "header-title": !removeTitle});
But i am not sure now that I have the div , I would appreciate some help here...
A solution outside of JSX would be very helpful
return (
<div className="result-title">
<div className={`header-${removeTitle ? 'without-title' : 'with-title'}`}>{pageTitle}</div>
</div>
);
or with use https://github.com/JedWatson/classnames
return (
<div className="result-title">
<div className={classNames({ 'header-without-title': removeTitle, 'header-with-title': !removeTitle })}>
{pageTitle}
</div>
</div>
);
EDIT:
A solution outside of JSX
const result = (
<div className={classNames({ 'header-without-title': removeTitle, 'header-with-title': !removeTitle })}>
{pageTitle}
</div>
);
return (
<div className="result-title">
{result}
</div>
);
You can just inline classNames function
const { pageTitle, removeTitle = false } = props;
const result = classNames({"header-without-title": removeTitle, "header-title": !removeTitle});
return (
<div className="result-title">
<div className={result}>
{pageTitle}
</div>
</div>);
);
There are several answers to this. Depends of each case
Ternary between two classes in React:
<div className={`header-${removeTitle ? 'without-title' : 'with-title'}`}>
Ternary between class or null in React Javascript:
<div className={removeTitle ? 'without-title' : null}>
Ternary between render class or not in React Javascript and Typescript:
<div className={...(removeTitle ? { className: 'without-title' } : {})}>

Test DOM jasmine

I am new in Unit Test JS. I want create test in jasmine. I dynamically create element HTML in JS.
data.map((channel) => {
const { url, width, height } = channel.thumbnails.medium;
const { title, customUrl } = channel;
const { subscriberCount, videoCount, viewCount } = channel.statistics;
output += `
<li class="channel-wrraper">
<a href='${customUrl}' target="_blank">
<img src='${url}' alt="img-channel" height='${width}' width='${height}' class="channel-img">
</a>
<p class="channel-title">${title}</p>
<div class="channel-statistic">
<div class="statistic-wrraper">
<span class="statistic-name">subscribers:</span>
<span class="subscirber-count">${formatNumber(subscriberCount)}</span>
</div>
<div class="statistic-wrraper">
<span class="statistic-name">videos:</span>
<span class="video-count">${formatNumber(videoCount)}</span>
</div>
<div class="statistic-wrraper">
<span class="statistic-name">views:</span>
<span class="veiw-count">${formatNumber(viewCount)}</span>
</div>
</div>
</li>`
});
channelsList.innerHTML = output;
Then some element will be ordered. This is sort function:
const list = document.querySelector('.channels-list');
const sortNumber = (selector) => {
[...list.children]
.sort((a,b) => a.querySelector(selector).innerText.replace(/,/g, '') - b.querySelector(selector).innerText.replace(/,/g, ''))
.map(node => list.appendChild(node))
}
I read about JSDOM and I watched the tutorials in which they tested the DOM, however, these elements were in the html file...
I want test function sortNumber
But I don`t know how start this task..
You can try using jsdom-global, then you will have document.body setup for you:
require('jsdom-global')()
// you can now use the DOM
document.body.innerHTML = 'put your html here'
An alternative will be to use jest, which comes with JSDOM configured as default

Categories