I'm new with React and before writing here I looked everywhere for my problem: I have a list with four items, and I want to show on hover different image for each item.
const [isShown, setIsShown] = useState(false);
return (
<div className="App">
<ul>
<li>
<a
onMouseEnter={() => setIsShown(true)}
onMouseLeave={() => setIsShown(false)}
href="/"
>
Item1
</a>
{isShown && (
<div style={{ width: `width: 300px` }}>
<img
className="image"
src="https://images.pexels.com/photos/1145720/pexels-photo-1145720.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260"
alt=""
/>
</div>
)}
</li>
...
I have used this procedure for each <li>
but no matter which item I hover, all images are shown.
Can someone help me? Thank you
Here the example
Update
I tried to use arrays as suggested by John but I am doing something wrong because the images are shown all together:
const projects = [
{ id: 1, title: "Item1" },
{ id: 2, title: "Item2" },
{ id: 3, title: "Item3" },
{ id: 4, title: "Item4" }
];
const images = [
{image: "https://placekitten.com/800/600", id: 1},
{image: "https://placekitten.com/800/600", id: 2},
{image: "https://placekitten.com/800/600", id: 3},
{image: "https://placekitten.com/800/600", id: 4},
];
function Portfolio(props) {
const [isShown, setIsShown] = useState(false);
return (
<section>
<div className="wrap">
<div className="container">
<ul className="wrap">
{props.projects.map((project, image) => (
<li key={project.id}>
<a
onMouseEnter={() => setIsShown(true)}
onMouseLeave={() => setIsShown(false)}
href="/"
>
{project.title}
</a>
{isShown && (
<img key={image.id} src={image} style={{position: `absoulte` }}/>
)}
</li>
))}
</ul>
</div>
</div>
</section>
);
This is because you're using the same flag isShown
to show all of the images. What you should do is change it from a boolean
to a int
and assign an index to it.
onMouseEnter={() => setIsShown(1)}
onMouseLeave={() => setIsShown(0)}
..
onMouseEnter={() => setIsShown(2)}
onMouseLeave={() => setIsShown(0)}
... etc
So for each image you'd have something like this
isShown === 1 && (
...code
)
isShown === 2 && (
...code
)
This way each image will depend on a specific value, making each of them independent.
A small suggestion. Since the code you're printing is redundant, I suggest you create an array
of your items and map them on the render instead of printing each item manually. Let me know if you have more questions about this.
Update:
I think there was a misunderstanding in what my suggestion was. I'm adjusting your code now, maybe now it will much clearer.
function Portfolio(props) {
const [isShown, setIsShown] = useState(false);
const projects = [
{ id: 1, title: "Item1", image: "https://placekitten.com/800/600" },
{ id: 2, title: "Item2", image: "https://placekitten.com/800/600" },
{ id: 3, title: "Item3", image: "https://placekitten.com/800/600" },
{ id: 4, title: "Item4", image: "https://placekitten.com/800/600" }
];
return (
<section>
<div className="wrap">
<div className="container">
<ul className="wrap">
{projects.map((project, image) => (
<li key={project.id}>
<a
onMouseEnter={() => setIsShown(project.id)}
onMouseLeave={() => setIsShown(0)}
href="/"
>
{project.title}
</a>
{isShown === project.id && (
<img src={project.image} style={{position: `absoulte` }}/>
)}
</li>
))}
</ul>
</div>
</div>
</section>
);
}
Let me know if you have any questions.