Reputation: 1004
I am working whit reactjs
to preview selected images in front. I have three image tags so I want to choose three images and show them in three different img tag
for preview. but now when I choose photo2
it previews it in photo1
. also the same as photo3
.
any help would be appreciated.
this is the image:
These are my functions:
const [picture1, setPicture1] = useState(null);
const [picture2, setPicture2] = useState(null);
const [picture3, setPicture3] = useState(null);
const [imgData1, setImgData1] = useState(data?.avatar?.url || null);
const [imgData2, setImgData2] = useState(data?.avatar?.url || null);
const [imgData3, setImgData3] = useState(data?.avatar?.url || null);
const onChangePicture1 = e => {
if (e.target.files[0]) {
setPicture1(e.target.files[0]);
const reader = new FileReader();
reader.addEventListener("load", () => {
setImgData1(reader.result);
});
reader.readAsDataURL(e.target.files[0]);
}
};
const onChangePicture2 = e => {
if (e.target.files[0]) {
setPicture2(e.target.files[0]);
const reader = new FileReader();
reader.addEventListener("load", () => {
setImgData2(reader.result);
});
reader.readAsDataURL(e.target.files[0]);
}
};
const onChangePicture3 = e => {
if (e.target.files[0]) {
setPicture3(e.target.files[0]);
const reader = new FileReader();
reader.addEventListener("load", () => {
setImgData3(reader.result);
});
reader.readAsDataURL(e.target.files[0]);
}
};
This is my code:
<div className="mt-6 grid sm:grid-cols-1 sm:gap-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3">
{imgData1 === null ? (
<File name="photo1" label={"Photo1"} onChange={onChangePicture1} />
) : (
<div className="sm:block">
<label
htmlFor="cover-photo"
className="block text-sm font-medium text-gray-700"
>
Photo 1
</label>
<div className="flex">
<div className="w-full">
<div className="justify-center px-2 pt-2 pb-2 border-2 border-gray-300 border-dashed rounded-md text-center">
<img
className="-mb-5 w-full h-28 object-cover"
src={imgData1}
/>
<label
htmlFor="file-upload"
className="p-0.5 relative cursor-pointer bg-white rounded-md font-medium text-indigo-600 hover:text-indigo-500 "
>
<span className="text-3xl">+</span>
<input
id="file-upload"
name="file-upload"
type="file"
onChange={onChangePicture1}
className="sr-only"
/>
</label>
</div>
</div>
</div>
</div>
)}
{imgData2 === null ? (
<File name="photo2" label={"Photo2"} onChange={onChangePicture2} />
) : (
<div className="sm:block">
<label
htmlFor="cover-photo"
className="block text-sm font-medium text-gray-700"
>
Photo 2
</label>
<div className="flex">
<div className="w-full">
<div className="justify-center px-2 pt-2 pb-2 border-2 border-gray-300 border-dashed rounded-md text-center">
<img
className="-mb-5 w-full h-28 object-cover"
src={imgData2}
/>
<label
htmlFor="file-upload"
className="p-0.5 relative cursor-pointer bg-white rounded-md font-medium text-indigo-600 hover:text-indigo-500 "
>
<span className="text-3xl">+</span>
<input
id="file-upload"
name="file-upload"
type="file"
onChange={onChangePicture2}
className="sr-only"
/>
</label>
</div>
</div>
</div>
</div>
)}
{imgData3 === null ? (
<File name="photo3" label={"Photo3"} onChange={onChangePicture3} />
) : (
<div className="sm:block">
<label
htmlFor="cover-photo"
className="block text-sm font-medium text-gray-700"
>
Photo 3
</label>
<div className="flex">
<div className="w-full">
<div className="justify-center px-2 pt-2 pb-2 border-2 border-gray-300 border-dashed rounded-md text-center">
<img
className="-mb-5 w-full h-28 object-cover"
src={imgData3}
/>
<label
htmlFor="file-upload"
className="p-0.5 relative cursor-pointer bg-white rounded-md font-medium text-indigo-600 hover:text-indigo-500 "
>
<span className="text-3xl">+</span>
<input
id="file-upload"
name="file-upload"
type="file"
onChange={onChangePicture3}
className="sr-only"
/>
</label>
</div>
</div>
</div>
</div>
)}
</div>
Upvotes: 1
Views: 501
Reputation: 196236
You have the same id on each file input id="file-upload"
, and you wrap all of them with a label with htmlFor="file-upload"
, so regardless of which button you click, you always trigger the first one.
Since your label wraps the input
, you do not need to use the htmlFor
property, and skipping it will cause each label to trigger its corresponding input
. But it is better to just fix the id
values and the relevant htmlFor
props.
In general, though
id
attributes throughout the pagefor
attribute (with the unique id
s) to maintain accessibility improvements.Upvotes: 2
Reputation: 889
try URL.createObjectUrl method
in react
export default function MyApp() {
const [previewUrl, setPreviewUrl] = useState('');
return (
<div>
<input type="file" onChange={(e) => {
const file = e.target.files?.[0];
if (file) {
setPreviewUrl(URL.createObjectURL(file));
}
}} />
{previewUrl && (
<img src={previewUrl} />
)}
</div>
)
}
Upvotes: 1