I am trying to add styles to the inidividual elements. I want when an individual div( is clicked to make sure that the paragraph of the specific changes from display: none to dislay:block. But the problem is, when I click only on one , all the paragraph text is displayed. here is the css below:
.cards{
background-color: red;
display: flex;
justify-content: center;
align-items: center;
height: 20vh;
}
[class*=cardDisplay]{
height: 80%;
display: flex;
align-items: center;
justify-content: center;
width: 200px;
background: black;
color: white;
margin: auto;
}
[class*=card-content]{
display: none;
}
[class*=card-content-2]{
display: block;
}
and the react.js file:
import React from 'react';
import {useState} from "react";
import "./game.css";
function Game() {
const [styling, setStyling] = useState("card-content")
const handleClick = () => {
setStyling("card-content-2")
}
return (
<div className="cards">
<div className="cardDisplay card-1" onClick={handleClick}>
<p className={styling}>Win</p>
</div>
<div className="cardDisplay card-2" onClick={handleClick}>
<p className={styling}>Sorry, No Win</p>
</div>
<div className="cardDisplay card-3" >
<p className={styling} onClick={handleClick}>Sorry, No Win</p>
</div>
</div>
)
}
CodePudding user response:
You're using only one styling
that you're applying to all paragraphs. If you want distinct styling for each paragraph, you have to hold that state separately for each paragraph.
Either:
Make the
div
paragraph
a component that holds its own state, orHave multiple
styling
state members (perhaps an array).
I would lean toward the first:
function Card({className = "", children}) {
const [styling, setStyling] = useState("card-content");
const handleClick = () => {
setStyling("card-content-2")
};
return (
<div className={`cardDisplay ${className}`} onClick={handleClick}>
<p className={styling}>{children}</p>
</div>
);
};
function Game() {
return (
<div className="cards">
<Card className="card-1">Win</Card>
<Card className="card-2">Sorry, No Win</Card>
<Card className="card-3">Sorry, No Win</Card>
</div>
);
}
There's lots of ways to spin that, but that's the basic idea.
But there's also an argument for the cards being an array of objects with state; here's an example with the results randomized when the component is first mounted:
function makeCards() {
const num = 3;
const win = Math.floor(Math.random() * num);
return Array.from({length: 3}, (_, index) => ({
id: `card-${index}`,
result: index === win ? "Win" : "Sorry, No Win",
showing: false,
}));
}
function Game() {
const [cards, setCards] = useState(makeCards);
const handleClick = (event) => {
const id = event.currentTarget.getAttribute("data-id");
setCards(prevCards => {
const newCards = prevCards.map(card => {
if (card.id === id) {
return {...card, showing: true};
}
return card;
});
return newCards;
});
};
return (
<div className="cards">
{cards.map(({id, result, showing}) => (
<div key={id} data-id={id} className={`cardDisplay ${id}`} onClick={handleClick}>
<p className={showing ? "card-content" : "card-content-2"}>{result}</p>
</div>
))}
</div>
);
}
CodePudding user response:
This may help you. It really works........
import React from 'react';
import {useState} from "react";
import "./game.css";
function Game() {
const handleClick = (e) => {
e.target.firstChild?.classList?.remove("card-content");
e.target.firstChild?.classList?.add("card-content-2");
};
return (
<div className="cards">
<div className="cardDisplay card-1" onClick={handleClick}>
<p className="card-content">Win</p>
</div>
<div className="cardDisplay card-2" onClick={handleClick}>
<p className="card-content">Sorry, No Win</p>
</div>
<div className="cardDisplay card-3" onClick={handleClick}>
<p className="card-content">Sorry, No Win</p>
</div>
</div>
);
}