**> This is my Gallery Component **
import React, {useState} from 'react';
import useFirestore from '../hooks/useFirestore';
import { motion } from 'framer-motion';
const Gallery = ({ setSelectedImg }) => {
const { docs } = useFirestore('images');
here im setting the state as a Tags array
const [tags, setTags] = useState([""]);
const addTag = (e) => {
if (e.key === "Enter") {
if (e.target.value.length > 0) {
setTags([...tags, e.target.value]);
e.target.value = "";
}
}
};
functions for adding and removing Tags
const removeTag = (removedTag) => {
const newTags = tags.filter((tag) => tag !== removedTag);
setTags(newTags);
};
return (
<>
<div className="img-grid">
{docs && docs.map(doc => (
< motion.div className="img-wrap" key={doc.id}
layout
whileHover={{ opacity: 1 }}s
onClick={() => setSelectedImg(doc.url)}
>
here Im adding the Tag input to each Image...the problem is that when adding a Tag is added to all the pictures. I want to add the tags for the image that I´m selecting.
<div className="tag-container">
{tags.map((tag, ) => {
return (
<div key={doc.id} className="tag">
{tag} <span onClick={() => removeTag(tag)}>x</span>
</div>
);
})}
<input onKeyDown={addTag} />
</div>
<motion.img src={doc.url} alt="uploaded pic"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 1 }}
>
</motion.img>
</motion.div>
))}
</div>
</>
)
}
export default Gallery;
The tags
array that you are using to store values entered by the user are not unique with respect to each image item
. Meaning, every image item in your program is using the same instance of the tags
array, what you need to do is
const [tagsObj, setTagsObj] = {}
, then while adding a new tag for say image_1
, you can simply do setTagsObj(prevObj => {...prevObj, image_1: [...prevObj?.image_1, newTagValue]}
,Image
Component which would then handle tags for a single image:Gallery Component:
{
imageList.map(imageEl =>
<ImageItem key={imageEl} image={imageEl} />
)
}
ImageItem Component:
import {useState} from 'react';
export default function ImageItem({image}) {
const [tags, setTags] = useState([]);
const addTag = (e) => {
if (e.key === "Enter") {
const newVal = e.target.value;
if (newVal.length > 0) {
setTags(prevTags => [...prevTags, newVal]);
e.target.value = '';
}
}
};
const removeTag = (removedTag) => {
setTags(prevTags => prevTags.filter((tag) => tag !== removedTag));
}
return (
<div style={{margin: '12px', padding: '12px', width: '100px', height:'100px', display:'flex', flexDirection: 'column', alignItems:'center'}}>
<span>{image}</span>
{tags.map((tag, index) => {
return (
<div key={tag+index}>
{tag} <span onClick={() => removeTag(tag)}>x</span>
</div>
);
})}
<input onKeyDown={addTag} />
</div>
);
}
Refer this sandbox for ease, if available Gallery unique image tags sandbox
I suggest using the second method, as it is easy to understand and debug later on.
I hope this helps, please accept the answer if it does!