Change Parent Background on Child Hover - javascript

so i have this code:
import React, {Component} from 'react';
import '../../styles/css/Home.css';
import $ from 'jquery';
export default class Home extends Component {
render(){
return(
<div className="menu">
<div className="middle">
<div className="menu-item btn-sobre"></div>
<div className="menu-item btn-questionario"></div>
<div className="menu-item btn-estresse"></div>
<div className="menu-item btn-depressao"></div>
<div className="menu-item btn-ansiedade"></div>
</div>
</div>
);
$(document).ready(function() {
$(".btn-sobre").on("mouseover", function() {
$(".menu").css("background-color", "red")
}).on("mouseout", function() {
$(".menu").css("background-color", "white")
});
});
}
}
i'm trying to change the "menu" background when i hover any "btn-*" class, but it doesn't work
what can i do in that case (avoiding jquery if possible)?

Don't mix jquery with react
Here is how you can achieve this using only react
import React, {Component} from 'react';
import '../../styles/css/Home.css';
export default class Home extends Component {
constructor() {
this.state = {
parentHover: false
}
}
render(){
return(
<div className="menu" style={parentHover ? {"backgroundColor": "red"} : {}}>
<div className="middle">
<div className="menu-item btn-sobre" onMouseOver={this.state.parentHover = true} onMouseOut={this.state.parentHover = false}></div>
<div className="menu-item btn-questionario" onMouseOver={this.state.parentHover = true} onMouseOut={this.state.parentHover = false}></div>
<div className="menu-item btn-estresse" onMouseOver={this.state.parentHover = true} onMouseOut={this.state.parentHover = false}></div>
</div>
</div>
);
}

if you are using jquery. You can use this code this will work for you. Thank You.
$(document).ready(function(){
$('.menu').find('.menu-item').mouseover(function(){
$(".menu").css("background-color", "white");
}).mouseleave(function(){
$(".menu").css("background-color", "red");
})
});

You could use the state of a component for this. And create a style variable that is connected to your menu div.
Info about react state: https://reactjs.org/docs/state-and-lifecycle.html
Use the react mouse events to trigger a function in your component and give it the color(a string) you want to use. You need to bind this and the color to your function in order for it to work.
More on react events: https://reactjs.org/docs/handling-events.html
class Home extends React.Component {
constructor(){
this.state = {
color: "white"
}
}
changeColor (color) {
this.setState({
color: color
})
}
render(){
let styles = {
backgroundColor: this.state.color
}
return (
<div className="menu" style={styles}>
<div className="middle">
<div onMouseOver={this.changeColor.bind(this, "#333")} className="menu-item btn-sobre">1</div>
<div onMouseOver={this.changeColor.bind(this, "#999")} className="menu-item btn-questionario">2</div>
<div onMouseOver={this.changeColor.bind(this, "#000")} className="menu-item btn-estresse">3</div>
<div onMouseOver={this.changeColor.bind(this, "#ccc")} className="menu-item btn-depressao">4</div>
<div onMouseOver={this.changeColor.bind(this, "#666")} className="menu-item btn-ansiedade">5</div>
</div>
</div>
);
}
}

Related

React map adding background color special elements

I use map but I have one problem I am trying to set the background of a certain element inside the map, in my case it is "item .title" I want my element to look like this https://ibb.co/ccJzD6g as you can see in the picture background color " 100% "which I specifically set in the console for but in fact if I set" background: orange "for the sidebar_list class, then the color will be applied to all elements including the rest , https://ibb.co/ZBTX3hd and if I set the background for the titleName class it looks like this https://ibb.co/84RKBBw but I want it to look like this https://ibb.co/ccJzD6g how do i solve this problem?
Lesson.jsx
import React from 'react';
import less from "./css/lesson.module.css";
import "./css/betaLesson.css";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { Navbar } from "../../../Navbar/Navbar";
export class Lessons extends React.Component {
constructor(props) {
super(props);
this.state = {
indexDescription: 0,
}
}
render() {
const listLessons = this.props.lesson.map((item, index) => {
return (
<li key={index} className={less.sidebar_list} onClick={() => {
this.setState({ indexDescription: index })
}}>
<div>
<FontAwesomeIcon className={less.item_icon} icon={item.iconName} />
</div>
<div style={{background: "orange"}} className={less.titleName}>
<p>{item.title}</p>
</div>
<div className={less.titleName}>
<p>{item.titleName}</p>
</div>
</li>
);
});
return (
<>
<div className="abc">
<Navbar color="blue" bg="tomato" centerFlexNavbarContainer="flex"
navbarSearchPage="Search" navbarHomePage="Home" centerHeadlineNavbarColumn="center" />
<div className={less.wrapper}>
<div>
<div className={less.sidebar}>
<div>
<ul>
{listLessons}
</ul>
</div>
</div>
</div>
<div className={less.main_content}>
<div className={less.main_inside_content}>
<div className={less.header}>
<div>
<h2>JavaScript JSON Reference</h2>
</div>
</div>
<div className={less.info}>
<div className={less.description}>
<p>
{
this.props.lesson[this.state.indexDescription]["description"]
}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
}
}
First question answer: Create a new component with its own attributes separately and map/passdown the properties to the component.
Here's an example: https://codesandbox.io/s/objective-hopper-2st8g?file=/src/Lesson.js

How to select a DOM element in React

When I am trying to use 'querySelector' or 'getElementById' to select a DOM element
I am getting Error: Value is null vs document.body that works just fine. Pls let me know if I am doing something wrong.
import React, { Component } from 'react';
import './main.styles.scss';
import { createChart } from 'lightweight-charts';
// const twoC = document.getElementById('twoCharts');
// const twoC = document.querySelector('.twoC');
// const body = document.body;
const twoC = document.querySelector('#twoCharts');
const chart = createChart(twoC, {
width: 1200,
height: 600,
});
class Main extends Component {
render() {
return (
<div className="main">
<div className="trading">
<div className="box one">1</div>
<div className="box twoC" id="twoCharts"></div>
</div>
<div className="charts">
<div className="box three">3</div>
<div className="box four">4</div>
</div>
</div>
);
}
}
export default Main;
React doesnt work that way, youll need to use a ref: https://reactjs.org/docs/refs-and-the-dom.html
import React, { Component, createRef } from 'react';
import './main.styles.scss';
import { createChart } from 'lightweight-charts';
const chart = createChart(twoC, {
width: 1200,
height: 600,
});
class Main extends Component {
// Create the ref
ref = createRef();
componentDidMount() {
// After the first render
console.log(this.ref.current); // Gets the current HTML element thats rendered
}
render() {
return (
<div className="main">
<div className="trading">
<div className="box one">1</div>
// Set the ref on this element
<div className="box twoC" id="twoCharts" ref={this.ref}></div>
</div>
<div className="charts">
<div className="box three">3</div>
<div className="box four">4</div>
</div>
</div>
);
}
}
export default Main;
While your statements above are using queryselector and getElementById are correctly written, they are unable to find a matching lelement because the render function has not yet been called.
On the contrary, the document's body is already defined and rendered, hence it does not return a null value. What you could do as a workaround is this:
import React, { Component } from 'react';
import './main.styles.scss';
import { createChart } from 'lightweight-charts';
const body = document.body;
const chart = createChart(body, {
width: 1200,
height: 600,
});
class Main extends Component {
const one,two,three;
getElements = () => {
this.one = document.getElementById('twoCharts');
this.two = document.querySelector('.twoC');
this.three = document.querySelector('#twoCharts');
//do something
}
render() {
return (
<div className="main">
<div className="trading">
<div className="box one">1</div>
<div className="box twoC" id="twoCharts"></div>
</div>
<div className="charts">
<div className="box three">3</div>
<div className="box four">4</div>
</div>
</div>
{this.getElements}
);
}
}

React state change not causing re-render

I am trying to toggle the visibility of a div when clicking a seperate div. The problem is it sets the div invisible on the first click and only if it is visible to begin with. After that it just stays invisible and will not update. The state is still being toggled in the console however.
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(){
super()
this.state = {
vis: '0'
}
}
toghide=()=>{
console.log("toggle login", this.state.vis)
if(this.state.vis === "hidden"){
console.log('showing')
this.setState((state, props)=>({vis:'0'}))
} else {
console.log('hiding')
this.setState((state, props)=>({vis:'hidden'}))
}
}
render() {
const styles = {
visibility: this.state.vis
}
return (
<div className="App">
<div className="salebar"><a className="salebar sale"
href="login">Click here!</a></div>
<div className="navbar">
<div className="nav"><div className="nnav">JMZ</div></div>
<div className="nav2"><div className="nnav2">PRODUCTS</div></div>
<div className="loginContainer"><div className="login" onClick={this.toghide}>LOGIN/SIGN UP</div></div>
</div>
<div className="login-container">
<div className="lognester">
<div style={styles} className="login-tab">
<input className="user" type="text" placeholder="Username"/>
<input className="password" type="password" placeholder="Password"/>
<button className="user">Login</button>
Sign in or <a className="register-link" href="register">register</a> a new account.
</div>
</div>
</div>
<div className="intro-pics"></div>
<div className="content"></div>
<audio preload loop controls autoPlay className="audio">
<source src="https://memefly.me/i/toValhalla.mp3"/>
Your browser does not support the audio element.
</audio>
</div>
);
}
}
export default App;
Try this:
class App extends Component {
constructor() {
super();
this.state = {
vis: true
};
}
toghide = () => {
this.setState({ vis: !this.state.vis });
};
render() {
return (
<div className="App">
<div className="salebar">
<a className="salebar sale" href="login">
Click here
</a>
</div>
<div className="navbar">
<div className="nav">
<div className="nnav">JMZ</div>
</div>
<div className="nav2">
<div className="nnav2">PRODUCTS</div>
</div>
<div className="loginContainer">
<div className="login" onClick={this.toghide}>
LOGIN/SIGN UP
</div>
</div>
</div>
<div className="login-container">
<div className="lognester">
{this.state.vis ? (
<div className="login-tab">
<input className="user" type="text" placeholder="Username" />
<input
className="password"
type="password"
placeholder="Password"
/>
<button className="user">Login</button>
Sign in or{' '}
<a className="register-link" href="register">
register
</a>{' '}
a new account.
</div>
) : (
''
)}
</div>
</div>
<div className="intro-pics" />
<div className="content" />
</div>
);
}
}
export default App;
This is the demo: https://codesandbox.io/s/72zzk2xr70
Two things are wrong with your code
It should be visibility:visible not visibility: 0. So change that.
Never ever ever ever... set state in your render function, really really bad practice.
1 ) You can declare your togHide method above render such as
toghide = () => {
//your code
}
render(){...}
2) You may handle visibility condition better if you just use true/false boolean logic on your vis state. This can be as :
constructor(){
super()
this.state = {
vis: true
}
}
toghide = () => {
if(this.state.vis){
this.setState({
vis : false
})}
else{
this.setState({
vis : true
})}
3) In toghide method, you can use the code for setState I've used above. You don't have to pass props if you don't use any, and don't need to use return in setState.

Update component with data from parent in React

In my react app I have this child component that inherits data from its parent. However, it does not update the page with new data from the child component when a relevant anchor link is clicked.
Here's my build - https://suite-search-lk.surge.sh/result/369523
From the link above if you click on a suggested card h1 element it just updates the URL with the id but does not update the page with the relevant card data from that id.
Any idea how I can fix this? Do I have to force the component to re-update?
Parent component (Card Wrapper)
class CardWrapper extends React.Component {
constructor(props) {
super(props);
this.state = {
stories: []
};
}
componentDidMount() {
axios
.get(API)
// .then(response => console.log(response))
// get our stories array, check it and then change state to contain our stories
.then(data => {
let stories;
if (data.data.stories && data.data.stories) {
if (Array.isArray(data.data.stories)) {
stories = data.data.stories;
} else {
stories = [data.data.stories];
}
} else {
stories = [];
}
this.setState({
stories: stories
});
});
}
render() {
return (
<CardWrapperDiv>
<div className="headingWrapper">
<div className="heading"> Suggested for you</div>
</div>
<Cards>
{this.state.stories.map(story => {
return (
<Card
title={story.content.title}
img={story.content.img}
description={story.content.description}
deadline={story.content.deadline_date}
tags={story.content.tags}
key={story.id}
id={story.id}
/>
);
})}
</Cards>
</CardWrapperDiv>
);
}
}
export default CardWrapper;
Child component
class Card extends React.Component {
render() {
return (
<CardDiv>
<div className="cardbox">
<div className="cardDetails">
<div className="headlineText">
<Link to={`/result/${this.props.id}`}> {this.props.title} </Link>
</div>
<div className="headlineSub">Colombo, Sri Lanka</div>
<div className="headlineDes">{this.props.description}</div>
<div className="textRemain">
{" "}
Deadline date: {this.props.deadline}
</div>
<div className="buttonRow">
<button className="downloadBtn">Download</button>
<button className="viewBtn">View</button>
</div>
</div>
<div className="cardimgwrapper">
<div className="cardimg">
<img src={this.props.img} alt="some title" />
</div>
</div>
</div>
</CardDiv>
);
}
}
export default Card;
Sorry it seems I have figured this out using the following post - Can you force a React component to rerender without calling setState?
Although I'm not exactly sure if it's the best way to go about it.
Essentially I used an OnClick listener to run a function and forces a re-render of the entire component.
Hope this can help someone else :)
class Card extends React.Component {
handleButtonClick() {
this.forceUpdate();
}
render() {
return (
<CardDiv>
<div className="cardbox">
<div className="cardDetails">
<div className="headlineText">
<Link to={`/result/${this.props.id}`} onClick={this.handleButtonClick}> {this.props.title} </Link>
</div>
<div className="headlineSub">Colombo, Sri Lanka</div>
<div className="headlineDes">{this.props.description}</div>
<div className="textRemain">
{" "}
Deadline date: {this.props.deadline}
</div>
<div className="buttonRow">
<button className="downloadBtn">Download</button>
<button className="viewBtn">View</button>
</div>
</div>
<div className="cardimgwrapper">
<div className="cardimg">
<img src={this.props.img} alt="some title" />
</div>
</div>
</div>
</CardDiv>
);
}
}
export default Card;
U have to use ur child component as a pure component. PureComponent Update when ur props change.
class Card extends React.PureComponent {
handleButtonClick() {
this.forceUpdate();
}
render() {
return (
<CardDiv>
.....
.....
</CardDiv>
);
}
}
export default Card;

Can I change the opacity state of a div located in a react component?

I am trying to separate my component and container code.
I know the function handleHide() in MainContainer is getting called when the Button "Hide" in Main.js gets pressed because the Alert located in the handleHide() function works.
So basically it's a matter of if opacity cannot be changed through props or I am missing something.
Below is my Main.js file (Component)
import React from 'react'
const styles = {
transition: 'all 1s ease-out'
}
export class Main extends React.Component {
render () {
return (
<div>
<nav>
<div className='nav-wrapper'>
<a href='/' className='brand-logo'>Todays’ EDM</a>
<ul id='nav-mobile' className='right hide-on-med-and-down'>
<li><a href='sass.html'>Music</a></li>
<li><a href='badges.html'>Playlists</a></li>
<li><a href='collapsible.html'>News</a></li>
</ul>
</div>
</nav>
<div className='container'>
<div className='row'>
<div className='s12' />
</div>
<div className='row'>
<div className='s8 offset-s2 center-align'>
<div className='card green accent-4 z-depth-2'
style={{...styles, opacity: this.props.opacity, transform: 'scale(' + this.props.scale + ')'}}>
<div className='card-content white-text'>
<span className='card-title'>Title</span>
</div>
<div className='card-action'>
<a onClick={this.props.hide}>HIDE</a>
</div>
</div>
</div>
</div>
</div>
</div>
)
}
}
This is my MainContainer.js file (Container)
import React from 'react'
import { Main } from '../components/Main'
export class MainContainer extends React.Component {
constructor (props) {
super(props)
this.state = {
opacity: 1,
scale: 1
}
this.handleHide = this.handleHide.bind(this)
this.handleScale = this.handleScale.bind(this)
}
handleHide () {
this.setState({
opacity: 0
})
alert('Goodbye world')
}
handleScale () {
this.setState({
scale: this.state.scale > 1 ? 1 : 1.2
})
}
render () {
let hide = this.handleHide
return (
<Main hide={hide} />
)
}
}
Modify your code in MainContainer.js as below...
<Main hide={hide} {...this.state} />

Categories