How can i hover in React using useState - reactjs

I wanna toggle a class when hovering on a Container by changing the opacity from 0 to 1, I've used onmouseEnter and onMouseLeave Event to toggle the class, but when I console hover state I see that is changing from true to false when I hover but the class "Show" is not changing.
What do you think ?
<--Components-->
import React,{useState} from 'react';
import './MyWork.css';
import {Visibility, GitHub } from "#material-ui/icons";
const SingleProject = ({src, title}) => {
const [hover, isHover] = useState(false);
const showIcons = isHover ? "Show" : "";
return (
<div className="card-container" onMouseEnter={()=> isHover(true)} onMouseLeave={()=> isHover(false)}>
<img src={src} alt={title}/>
<h1 id="card-title">{title}</h1>
<div className={`Info ${showIcons}`}>
<div className="Icon">
<GitHub/>
</div>
<div className="Icon">
<Visibility/>
</div>
</div>
</div>
)
}
export default SingleProject;
<--- Css--->
.card-container {
height: 314px;
width: 500px;
cursor: pointer;
position : relative;
}
.Info {
position: absolute;
height: 100%;
width: 100%;
top:0;
left:0;
display:flex;
justify-content:center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
}
.Info.Show {
opacity: 1;
}

When assigning the value to showIcons, you need to use hover instead of isHover which is the setter function for that state.
Additionally, I recommend naming the setter function setHover to avoid confusion and be more semantic. You can also add conditional Show class like this, which is more concise:
iconst SingleProject = ({src, title}) => {
const [hover, setHover] = useState(false);
return (
<div
className="card-container"
onMouseEnter={()=> setHover(true)}
onMouseLeave={()=> setHover(false)}
>
<img src={src} alt={title}/>
<h1 id="card-title">{title}</h1>
<div className={`Info ${hover ? "Show" : ""}`}>
<div className="Icon">
<GitHub/>
</div>
<div className="Icon">
<Visibility/>
</div>
</div>
</div>
)
}
export default SingleProject;

You are using the setter instead of the state itself on your condition. Change isHover with hover like below:
const showIcons = hover ? "Show" : "";

Related

React - Modal expands div in footer div not on main screen

New to coding, trying to get a modal to work. It is not opening the way I expected it to.
The component is currently loaded within the footer div of my site. And when the button is toggled it simply hides or shows a div within the footer. I want it to appear in the centre of the webpage as a modal.
import React, {useState} from 'react';
import './policy.css'
export default function Policy() {
const [modal, setModal] = useState(false);
const toggleModal = () => {
setModal(!modal);
};
if(modal) {
document.body.classList.add('active-modal')
} else {
document.body.classList.remove('active-modal')
}
return (
<>
<div>
<button onClick={toggleModal} className='btn-modal'>
<p>Privacy Policy</p>
</button>
</div>
{modal && (
<div className="modal">
<div onClick={toggleModal} className="overlay"></div>
<div className="modal-content">
<h2>Privacy Policy</h2>
<p>This is the privacy policy</p>
<button className='close-modal' onClick={toggleModal}>Close</button>
</div>
</div>
)}
</>
);
}
The simplest way to achieve a modal effect is to use some CSS.
You could try a very crude style like (from MUI Modal docs):
const style = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 400,
bgcolor: "lightgrey",
border: "2px solid #000",
boxShadow: 24,
padding: 4,
};
Then apply it to your modal:
<div className="modal" style={style}>

How can i create a new div when i onclick the button in React js?

code 1 component:-
const TableheaderText = props => {
//const [playlist, setPlaylist] = useState(props);
const [playlist, setPlaylist] = useState("playlist");
const [showing, SetShowing] = useState();
const [isActive, setActive] = useState(true);
//console.log(playlist);
useEffect(() => {
// setPlaylist(props);
SetShowing("PLAYLIST:");
setPlaylist(props.val);
}, [props])
return (
<div className="mainContent">
<div className="tableHeaderBody" >
<div className="TableText" >
<div id="HIDE">{showing}</div><div id="SHOW">{playlist}</div>
</div>
<div className="ClossIcon"><FaCircle style={{ color: "#FC0000", width: "10px", height: "10px", alignItems: "right" }} /></div>
</div>
</div>
)
}
code 2 component:-
<NavLink to={`/Table`} onClick={(e) => myClick(val, index)} >
<button className='notActive buttonLeft'
onClick={() => handleOnClick(index)} // pass the index
className={activeIndex === index ? "active" : "notActive"}>
{val}
</button>
</NavLink>
Right now i have one div and when i click the menu value then one div replace the name
but i want that when i click the 1 value its create one div and when click the 2 value its create second div with the name of 2 div and place right side of 1 div and so.. (if 3,4 value menu ..)
This may be one possible solution to achieve the desired objective (copied from OP's question):
i want that when i click the 1 value its create one div and when click
the 2 value its create second div with the name of 2 div and place
right side of 1 div and so..
Code Snippet
const {useState} = React;
const Thingy = () => {
const myDivs = [...Array(4).keys()].map(i => `My Div # ${i+1}`);
const [flipDivs, setFlipDivs] = useState([
...myDivs.map(
(text, id) => ({id, text, show: false})
)
]);
const handleClick = e => {
const idx = e.target.id;
const newArr = [...flipDivs];
newArr[idx].show = !flipDivs[idx].show;
setFlipDivs(newArr);
};
const myButtons = [...Array(4).keys()];
return (
<div>
<div class="allDivs">
<div> Fixed Div </div>
{
flipDivs.filter(({show}) => !!show).map(
({text, id, show}, idx) => (
<div
key={idx}
class="simpleMargin rightBorder"
>
{text}
</div>
)
)
}
</div>
<div class="buttons">
{myButtons.map(id => (
<button
id={id}
class="simpleMargin"
onClick={handleClick}
>
{flipDivs[id].show ? 'Hide' : 'Show'} Div # {id+1}
</button>
))}
</div>
</div>
);
};
ReactDOM.render(
<div>
DEMO
<Thingy />
</div>,
document.getElementById("rd")
);
.allDivs {
border: 2px solid black;
width: fit-content;
display: flex;
align-items: center;
margin: 10px 15px;
}
.simpleMargin { margin: 5px 10px; }
.rightBorder { border: 2px solid black; }
.buttons {
display: flex;
margin: 10px 5px;
}
<div id="rd" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
Explanation
simple, straightforward approach
Add a flag to determine which div needs to be rendered on which button click
On the click-handler, simply update the flag to show / hide div
For this you need to make a div element and whoe it conditionally ( with state declared with useState ) and then toggle the state on button click to show it. like :
{
showDiv ? <div></div> : null
}
Here showDiv is:
const [showDiv, setShowDiv] = useState (false)
Now toggle showDiv on button click to true. :)

Radio button style changes when clicked with React Hooks

I want the radio button to change when clicked. This is what i have now image
I want it to change to this when clicked
Here's my code: `
const [active, setIsActive] = useState(false)
<div className={`checkbox payment-radio-btn1 ${active ? "checkbox:hover" : "" }`}>
<input type="radio" value="paystack" name='payment' onChange={handleChange}/>
<label id='paystack'>Paystack (Debit/Credit Card)</label>
</div>
<div className={`checkbox payment-radio-btn2 ${active ? "checkbox:hover" : "" }`}>
<input type="radio" value="wallet" name='payment' onChange={handleChange}/>
<label id='wallet'>Pay with Wallet</label>
</div>
Here's my css code
.checkbox:hover{
border: 2px solid #00B6F0;
background: #FFFFFF;
}
.payment-radio-btn1{
position: absolute;
width: 406px;
height: 64px;
left: 10px;
top: 128px;
background: #F3F4F5;
box-shadow: 0px 24px 38px 3px rgba(0, 0, 0, 0.14);
border-radius: 4px;
margin-top: 20px;
margin-left: 6px;
display: flex;
}
One option is a custom Radio element that allows you to represent your radio buttons however you like. In this example we use two emoji, but you could use images, or SVG if you wanted.
function Radio({ checked, onClick, children, on = "✔️", off = "🟡" }) {
return <div className="radio" onClick={onClick}>
{checked ? on : off } {children}
</div>
}
We can use the Radio elements in our app like this.
function App() {
const [radio, selectRadio] =
useRadio(["paystack", "paypal", "wallet"], "paystack")
return <div>
<Radio checked={radio == "paystack"} onClick={selectRadio("paystack")}>
Paystack (Debit/Credit Card)
</Radio>
{/* more radio options ...*/}
</div>
}
This is made possible by writing useRadio which encodes the radio group logic nicely in a custom hook.
function useRadio(validStates, initState) {
const [state, setState] = React.useState(initState)
return [
state,
value => event =>
validStates.includes(value)
? setState(value)
: console.error(`invalid option: ${value}`)
]
}
Here's a minimal, verifiable example. Run it below and click some radio buttons to see the application state change.
function App() {
const [radio, selectRadio] = useRadio(["paystack", "paypal", "wallet"], "paystack")
return <div>
<Radio checked={radio == "paystack"} onClick={selectRadio("paystack")}>
Paystack (Debit/Credit Card)
</Radio>
<Radio checked={radio == "wallet"} onClick={selectRadio("wallet")}>
Pay with Wallet
</Radio>
<Radio checked={radio == "paypal"} onClick={selectRadio("paypal")}>
PayPal
</Radio>
<pre>{JSON.stringify({paymentOption: radio}, null, 2)}</pre>
</div>
}
function Radio({ checked, onClick, children, on = "✔️", off = "🟡" }) {
return <div className="radio" onClick={onClick}>
{checked ? on : off } {children}
</div>
}
function useRadio(validStates, initState) {
const [state, setState] = React.useState(initState)
return [
state,
value => event =>
validStates.includes(value)
? setState(value)
: console.error(`invalid option: ${value}`)
]
}
ReactDOM.render(<App/>, document.querySelector("#app"))
.radio { cursor: pointer; }
pre { padding: 0.5rem; background-color: #ffc; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Problems with Styled-Components conditional style rendering. I'm not sure what's wrong

I'm trying to toggle a hamburger menu on and off. I've console logged to check that the boolean values are changing, but the css isn't.
My issue is with 'props.active?' it's working but the '.mobile-menu' class is not changing. I'm not entirely sure what I need to do to get it to work. I've tried to make changes to the style I want to affect because I thought maybe you can't toggle as display, however,f visibility and opacity still aren't changing either.
import { useState } from "react";
import styled from "styled-components";
import logo from "./assets/logo.svg";
const StyledHeader = styled.header`
---
button {
---
span {
---
&:nth-child(even) {
margin: 5px 0;
}
}
}
.mobile-menu {
position: absolute;
right: 100px;
top: 100px;
display: ${(props) => (props.active ? "none" : "block")};
height: 330px;
width: 330px;
background: #e210e2;
color: white;
ul {
----
}
}
`;
const Header = () => {
const [active, setActive] = useState(false);
return (
<StyledHeader>
<img src={logo} alt="sunnyside logo" />
<button onClick={() => setActive(!active)}>
{console.log(active)}
<span></span>
<span></span>
<span></span>
</button>
<nav className="mobile-menu" active>
<ul>
<li>About</li>
<li>Services</li>
<li>Projects</li>
<li>Contact</li>
</ul>
</nav>
</StyledHeader>
);
};
export default Header;
Please pass the props in the StyledHeader tag.
Follow the below code:
<StyledHeader active={active}>
....
</StyledHeader>
You're not passing the active prop. You need to pass the active prop to the StyledHeader component to apply the styles like below.
<StyledHeader active={active}>
Updated Code will be like this.
<StyledHeader active={active}>
<img src={logo} alt="sunnyside logo" />
<button onClick={() => setActive(!active)}>
{console.log(active)}
<span></span>
<span></span>
<span></span>
</button>
<nav className="mobile-menu" active>
<ul>
<li>About</li>
<li>Services</li>
<li>Projects</li>
<li>Contact</li>
</ul>
</nav>
</StyledHeader>

add background color onClick in react

so i have this flexbox:
[![flexbox][1]][1]
what i need is this:
when i press on any the divs on the left from overview to the bottom i need it to be colored in white the background just like in the image, i'm new to react and i'm trying to go through this project can anyone help me with this i'm stuck.
code so far:
flexbox.js:
const sidebar = (props) => (
<div>
<div className="container">
<div className="flex-item item-1" onClick={}>John Smith</div>
<div className="flex-item item-2">Male, 26 years old</div>
<div className="flex-item item-3">Overview</div>
<div className="flex-item item-4">Alerts</div>
<div className="flex-item item-5">Recent</div>
<div className="flex-item item-6">Blood Pressure</div>
<div className="flex-item item-7">Body Weight</div>
<div className="flex-item item-8">Glucose</div>
<div className="flex-item item-9">SpO2</div>
<div className="flex-item item-10"><FontAwesomeIcon icon={faCog}/></div>
</div>
</div>
);
flexbox.css:
.container {
border: 2px solid #57c0e8;
background-color: #57c0e8;
margin-top: 4%;
float: left;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
color:white;
display: flex;
flex-direction: column;
height:40rem;
width:15rem;
flex-wrap: wrap;
justify-content: flex-start;
align-items: flex-start;
font-size:0.9rem;
}
.flex-item{
margin-top: 2rem;
}
.item-2 {
margin-top: 0rem;
}
.item-3 {
margin-top: 5rem;
}
.item-10{
align-self:center;
}
If you really want to keep your code as it is now, you could simply add a class on each flex item and an onClick method to add a class on the selected item and remove the class on the others.
here is how you can do that :
const MyList = () => {
const setSelectedItem = e => {
Array.from(document.getElementsByClassName("item"))
.forEach(item => item.classList.remove("selected"));
e.target.classList.add("selected");
};
return (
<div>
<ul>
<li className="item" onClick={setSelectedItem}>
item 1
</li>
<li className="item" onClick={setSelectedItem}>
item 2
</li>
<li className="item" onClick={setSelectedItem}>
item 3
</li>
<li className="item" onClick={setSelectedItem}>
item 4
</li>
</ul>
</div>
);
};
But I suggest you to refactor your code to build your sidebar list dinamically, It will be way easier to manage. You can do it this way, with an array containing your data and looping over it :
import React, { Component } from "react";
import { render } from "react-dom";
import Hello from "./Hello";
import "./style.css";
const App = () => {
const data = [
{ name: "item 1", isSelected: false },
{ name: "item 2", isSelected: false },
{ name: "item 3", isSelected: false },
{ name: "item 4", isSelected: false }
];
const [items, setItems] = React.useState(data);
const setSelectedItem = selectedItem => {
const newItems = [...items];
newItems.forEach(item => {
item.isSelected = item.name === selectedItem.name;
});
setItems(newItems);
};
const buildList = () => {
return items.map(item => (
<li className={item.isSelected ? 'selected':''} onClick={() => setSelectedItem(item)}>
{item.name}
</li>
));
};
return <ul>{buildList()}</ul>;
};
render(<App />, document.getElementById("root"));
Then you only have to write the css on .selected:
li{
padding: 10px;
}
.selected{
background-color: lightskyblue;
border-radius: 50px 0 0 50px;
box-shadow: 2px 2px 5px lightgray;
}
Here is the repro on stackblitz.
Here is used a list but it changes nothing compared to you using flexbox.
Ok, so I'm thinking you could do it by making an active class in your css to make it white:
.sidebarActive {
background:#fff
...
...
}
Then, add a state to your component that can store a string (Or I guess it could be a number and your could store the index of the selected div). This would looks something like:
const sidebar = (props) => {
const [selectedDiv,setSelectedDiv] = React.useState(null)
return (
<div>
<div className="container">
<div className="flex-item item-1" onClick={}>John Smith</div>
...
</div>
</div>
)
}
Then, your onClick function needs to set the state to the correct div:
<div className="flex-item item-1" onClick={()=>setSelectedDiv('John Smith')}>John Smith</div>
And finally, you need to add a conditional to the classNames of the divs - to check if the state is selecting this div:
<div className={
selectedDiv === "John Smith"
?
"flex-item item-1 sidebarActive"
:
"flex-item item-1"
}
onClick={...}
>
John Smith
</div>
There are then many ways to optimise this - Like adding your divs into an array, so that you don't need to type "John Smith", "Overview", "Alerts" and all the rest of them multiple times.
But, this should be enough info to get you somewhere!
Hope it helps :)

Resources