Zia Yamin
Zia Yamin

Reputation: 1004

How to preview images in javascript?

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:

enter image description here

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

Answers (2)

Gabriele Petrioli
Gabriele Petrioli

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

  • use unique id attributes throughout the page
  • use the for attribute (with the unique ids) to maintain accessibility improvements.

Upvotes: 2

Kay
Kay

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

Related Questions