import React from "react";
import "./About.css";
import About_Main from "../components/About_Main";
import About_Data1 from "../components/About_Data1";
import About_Data2 from "../components/About_Data2";
class About extends React.Component {
state = {
main: {
display:"block",
opacity:1
},
data: {
display:"none",
opacity:0
}
};
changeSelect = id => {
if (id === "select1") {
this.setState({
main: {
display:"block",
opacity:1
},
data: {
display:"none",
opacity:0
}});
} else if (id === "select2") {
this.setState({
main: {
display:"none",
opacity:0
},
data: {
display:"block",
opacity:1
}});
}
};
clickHandler = event => {
event.preventDefault();
this.changeSelect(event.target.id);
};
render() {
return (
<div>
<section className="selects">
<div
id="select1"
className="select"
onClick={this.clickHandler}
></div>
<div
id="select2"
className="select"
onClick={this.clickHandler}
></div>
</section>
<section className="about">
<div
className="about_div"
style={{ display: this.state.main.display, opacity: this.state.main.opacity }}
>
<About_Main></About_Main>
</div>
<div
className="about_data"
style={{ display: this.state.data.display, opacity:this.state.data.opacity }}
>
<About_Data1></About_Data1>
<About_Data2></About_Data2>
</div>
</section>
</div>
);
}
}
export default About;
By clicking 2 different buttons, I want to show only one out of two.
Also, I like to give a transition effect so I used opacity. But it is not working!
Is this the only way to set style property using javascript in react?
Can't I use querySelector or something else?
I feel like javascript is much easier than react ðŸ˜ðŸ˜
Related
I am trying to display FontAwesomeicon
<font-awesome-icon icon="fa-solid fa-shop" />
with JavaScript array to be dynamic but it's not working it displays as text
<div class="aboutme-card" v-for="(item,index) in servicesArr" :key="index">
<div class="service-card-icon">{{item.icon}}</div> <!--but its display as text not as icon svg-->
<div class="service-card-title">{{item.title}}</div>
<p class="service-card-desc">{{item.description}}</p>
</div>
<script>
export default {
data() {
return {
servicesArr: [
{
icon: `<font-awesome-icon icon="fa-solid fa-shop" />`,
title: "E-commerce",
}
]
}
}
}
</script>
Isn't something like this conceivable in your case?
<template>
<div class="aboutme-card" v-for="item in servicesArr" :key="item.icon">
<div class="service-card-icon">
<font-awesome-icon :icon="item.icon" />
</div>
</div>
</template>
<script>
export default {
data() {
return {
servicesArr: [
{
icon: "fa-solid fa-shop",
title: "E-commerce",
}
]
}
}
}
</script>
Even if v-html exists, it's usually not the way to go.
Especially in such a simple use-case where dynamic props are totally fine.
Overall, I still recommend that solution for overall ease of use + flexibility.
I'm trying to rotate a chevronDown button in react.js but the button is static.
here is my code.
import React, { useState, useEffect, useRef } from 'react'
import { chevronDown } from '../assets';
import styles from '../styles';
import { useOnClickOutside } from '../utils';
const AmountIn = () => {
const [showList, setShowList] = useState(false);
return (
<div className={styles.amountContainer}>
<input
placeholder="0.0"
type="number"
value=""
disabled={false}
onChange={() => {}}
className={styles.amountInput}
/>
<div className="relative" onClick={() => setShowList((prevState) => !prevState)}>
<button className={styles.currencyButton}>
{"ETH"}
<img
src={chevronDown}
alt="chevron down"
className={'w-4 h-4 object-contain ml-2 ${showList ? 'rotate-180' : 'rotate-0'}'}
/>
</button>
</div>
</div>
)
}
export default AmountIn
I'm expecting the button to rotate when the cursor is pointed at the button.
You can do this with the CSS :hover selector using transform. In your CSS module, you would use something like this to flip a chevron around
.currencyButton {
// core styling
&:hover {
img {
transform: rotate(0.5turn);
}
}
}
To expand on that, you can animate the change using a CSS transition.
Summary:
I have this logo in my website header, I want this logo (image [1]) to change to another one (image [2]) on scrolling down, and to change back to the original logo (image [1]) when I scroll back to the top.
What i tried:
I tried to make it with EventListener and useEffect in the header page, but I'm getting this error below:
ERROR in src\layouts\Navbar\index.jsx
Line 12:3: 'listenScrollEvent' is not defined no-undef
My code:
import React, { useState } from 'react'
import { useEffect } from "react";
export default () => {
useState = {
imageSrc: '',
imageAlt: ''
}
listenScrollEvent = e => {
if (window.scrollY > 400) {
this.setState({
imageSrc: './/img/Smartlogger_logo.png',
imageAlt: 'smartlogger white logo'
})
} else {
this.setState({
imageSrc: './../../views/Home/image/smartLoggerheader_logo.png',
imageAlt: 'smartlogger colored logo'
})
}
}
useEffect(() => {
window.addEventListener('scroll', this.listenScrollEvent)
}, []);
return (
<header className='header-area header-sticky'>
<div className='container'>
<div className='row'>
<div className='col-12'>
<nav className='main-nav'>
{/* ***** Logo Start ***** */}
<a href='/#' className='logo'>
<style>{css}</style>
<img
src={this.setState}
alt='Smartlogger logo'
/>
</a>
{/* ***** Logo End ***** */}
</nav>
</div>
</div>
</div>
</header>
)
}
You need to make the following changes in your code. It should fix the issue.
Inside render() - img src replace src={this.setState} with src={this.state.imageSrc}
Inside listenScrollEvent function replace window.scrollY with event.srcElement.body.scrollY
it will look like this (I have used random images here):
listenScrollEvent = event => {
if (event.srcElement.body.scrollY > 400) {
this.setState({
imageSrc: 'https://c.tenor.com/57w9du3NrV0AAAAS/css-html.gif',
imageAlt: 'smartlogger white logo'
})
} else {
this.setState({
imageSrc: 'https://c.tenor.com/57w9du3NrV0AAAAS/css-html.gif',
imageAlt: 'smartlogger colored logo'
})
}
}
Full working code : (I have added style={{height:'200vh'}} on container div just to test it on my local. You can remove it)
import React from 'react'
import { Link } from 'react-router-dom'
export default class App extends React.Component {
state = {
imageSrc: 'https://c.tenor.com/TReUojNlZ6wAAAAi/js-javascript.gif',
imageAlt: ''
}
listenScrollEvent = event => {
if (event.srcElement.body.scrollY > 400) {
this.setState({
imageSrc: 'https://c.tenor.com/57w9du3NrV0AAAAS/css-html.gif',
imageAlt: 'smartlogger white logo'
})
} else {
this.setState({
imageSrc: 'https://c.tenor.com/57w9du3NrV0AAAAS/css-html.gif',
imageAlt: 'smartlogger colored logo'
})
}
}
componentDidMount() {
window.addEventListener('scroll', this.listenScrollEvent)
}
render() {
return (
<header className='header-area header-sticky'>
<div className='container' style={{height:"200vh"}}>
<div className='row'>
<div className='col-12'>
<nav className='main-nav'>
{/* ***** Logo Start ***** */}
<a href='/#' className='logo'>
{/* <style>{css}</style> */}
<img
src={this.state.imageSrc}
alt='Smartlogger logo'
/>
</a>
{/* ***** Logo End ***** */}
</nav>
</div>
</div>
</div>
</header>
)
}
}
Hope that's how you wanted it to work. Try running it on your local and then you can modify it as per your requiremnets.
In your useState hook you want to have your src and your alt.
Remember useState return an array of 2 elements, the first is the value and the second is the setter for that value.
You can use the setter in your listenScrollEvent function and you can use the value in your jsx.
You are also using a css variable in you jsx that isn't defined anywhere.
It should look something like this:
import React, { useState, useEffect } from "react";
export default () => {
const [image, setImage] = useState({
src: "",
alt: "",
});
const listenScrollEvent = (e) => {
if (window.scrollY > 400) {
setImage({
src: "../img/Smartlogger_white_logo.png",
alt: "smartlogger white logo",
});
} else {
setImage({
src: "../img/Smartlogger_colored_logo.png",
alt: "smartlogger colored logo",
});
}
};
useEffect(() => {
window.addEventListener("scroll", listenScrollEvent);
}, []);
return (
<header className="header-area header-sticky">
<div className="container">
<div className="row">
<div className="col-12">
<nav className="main-nav">
{/* ***** Logo Start ***** */}
<a href="/#" className="logo">
<style>{css}</style>
<img src={require(image.src)} alt={image.alt} />
</a>
{/* ***** Logo End ***** */}
</nav>
</div>
</div>
</div>
</header>
);
};
An alternative solution that looks a little cleaner to me:
import React, { useState, useEffect } from "react";
import whiteLogo from "../img/Smartlogger_white_logo.png";
import coloredLogo from "../img/Smartlogger_colored_logo.png";
export default () => {
const [isScrolled, setIsScrolled] = useState(false);
const listenScrollEvent = (e) => setIsScrolled(window.scrollY > 400);
useEffect(() => {
window.addEventListener("scroll", listenScrollEvent);
}, []);
return (
<header className="header-area header-sticky">
<div className="container">
<div className="row">
<div className="col-12">
<nav className="main-nav">
{/* ***** Logo Start ***** */}
<a href="/#" className="logo">
<style>{css}</style>
<img
src={isScrolled ? whiteLogo : coloredLogo}
alt={
isScrolled
? "SmartLogger white logo"
: "SmartLogger colored logo"
}
/>
</a>
{/* ***** Logo End ***** */}
</nav>
</div>
</div>
</div>
</header>
);
};
EDIT: added note about css variable, fixed typo in code and formatted better
EDIT2: fixed image link and added the require in the img src attribute, this should fix the image loading
EDIT3: added alternative solution
I'm new to angular and I tried to make an accordion component, and it' didn't work like I wanted it to, here's my html code.
<div class="faq-item-container">
<h1 class="mt-1 mb-5"><strong>Frequently Aksed Questions</strong></h1>
<div class="row" (click)="toggleDetail(); toggleIcon();" *ngFor= "let faq of faqs">
<div class="col my-2">
<h3> {{faq.title}} <a><fa-icon [icon]="faChevronDown" class="float-right"></fa-icon></a></h3>
</div>
<div class="col-12" *ngIf="showDetail">
<div class="faq-detail-container mt-1">
<div class="col-12">
<p><small>
{{faq.content}}
</small></p>
</div>
</div>
</div>
</div>
</div>
and here's the ts code
import { Component, OnInit } from '#angular/core';
import {faChevronUp, faChevronDown, IconDefinition, faSquare} from '#fortawesome/free-solid-svg-icons';
#Component({
selector: 'app-jobs-faq',
templateUrl: './jobs-faq.component.html',
styleUrls: ['./jobs-faq.component.scss']
})
export class JobsFaqComponent implements OnInit {
faChevronUp: IconDefinition = faChevronUp;
faChevronDown: IconDefinition = faChevronDown;
showDetail: boolean;
faqs = [
{
id: 1,
title: 'faq1',
content: 'content1'
},
{
id: 2,
title: 'faq2',
content: 'content2'
},
{
id: 3,
title: 'faq3',
content: 'content3'
}
];
constructor() {
this.showDetail = false;
}
toggleDetail(): void {
this.showDetail = !this.showDetail;
}
toggleIcon() {
if (this.faChevronDown === faChevronDown) {
this.faChevronDown = faChevronUp;
} else {
this.faChevronDown = faChevronDown;
}
}
ngOnInit() {
}
}
The problem is when I click faq1, the others also collpasing, yes I know it's because I called the same function, and that is what I want to ask about, how to call the function separately to make this accordion working like it's supposed to be? thanks.
It depends on whether you want to close all other sections when you click one or not, but a solution could look somewhat like this:
<div class="faq-item-container">
<h1 class="mt-1 mb-5"><strong>Frequently Aksed Questions</strong></h1>
<div class="row" (click)="toggleDetail(faq.id); toggleIcon();" *ngFor= "let faq of faqs">
<div class="col my-2">
<h3> {{faq.title}} <a><fa-icon [icon]="faChevronDown" class="float-right"></fa-icon></a></h3>
</div>
<div class="col-12" *ngIf="faq.showDetail">
<div class="faq-detail-container mt-1">
<div class="col-12">
<p><small>
{{faq.content}}
</small></p>
</div>
</div>
</div>
</div>
</div>
import { Component, OnInit } from '#angular/core';
import {faChevronUp, faChevronDown, IconDefinition, faSquare} from '#fortawesome/free-solid-svg-icons';
#Component({
selector: 'app-jobs-faq',
templateUrl: './jobs-faq.component.html',
styleUrls: ['./jobs-faq.component.scss']
})
export class JobsFaqComponent implements OnInit {
faChevronUp: IconDefinition = faChevronUp;
faChevronDown: IconDefinition = faChevronDown;
faqs = [
{
id: 1,
title: 'faq1',
content: 'content1',
showDetail: false
},
{
id: 2,
title: 'faq2',
content: 'content2',
showDetail: false
},
{
id: 3,
title: 'faq3',
content: 'content3',
showDetail: false
}
];
toggleDetail(faqId: number): void {
this.faqs = this.faqs.map(faq => {
faq.showDetail = (faq.id == faqId) ? !faq.showDetail : false;
return faq;
});
}
toggleIcon() {
if (this.faChevronDown === faChevronDown) {
this.faChevronDown = faChevronUp;
} else {
this.faChevronDown = faChevronDown;
}
}
ngOnInit() {
}
}
Note that your [icon]="faChevronDown" should be based on the faq in the thes scope of your *ngFor. I'll leave it to you as practice to find a solution for that. (Hint: you could use a ternary operation based on faq.showDetail)
.storyMobile{
color:green;
}
.storyWeb{
color:red;
}
<div class="storyMobile">
hii
</div>
<div class="storyWeb">
hii
</div>
//main view
<div>
<story :story="stories[0]"/>
</div>
//here it prints stories in red colour but I want it to be displayed in green colour - how can I do this?
This is my component where I have 2 divs with 2 different classes one will be active for mobile and one will be active for web.
<div class="storyMobile">
//code
</div>
<div class="storyWeb">
//code
</div>
//this is my main view where I am importing this component
<div class="body-frame">
<Header></Header>
<section class="content-section-bar" v-if="stories && stories.length">
<div>
<story :story="stories[0]"/>
</div>
</section>
</div>
By default the story component is in web so "storyweb" class is getting applied to it but I want the "storyweb" class to get applied on it.
How should I do it in vue.js I tried using the props but didn't get the desired output.
Is it what you want?
your component:
<div :class="className"></div>
script:
export default {
props: {
className: {
default: 'storyWeb'
}
}
}
usage:
<story :story="stories[0]"/>
<story :story="stories[0]" class-name="storyMobile"/>
Vue.component('story',{
template: `<div :class="className">test</div>`,
props: {
className: {
type: String,
default: 'storyWeb'
},
story: {
type: Object,
required: true
}
}
})
var app = new Vue({
el: '#app',
data () {
return {
stories: [
{content: 'sotry1 content'},
{content: 'story2 content'}
]
}
}
})
.storyMobile{
color:green;
}
.storyWeb{
color:red;
}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<story :story="stories[0]" class-name="storyMobile"></story>
<story :story="stories[1]"></story>
</div>