最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - 3 instances of a component, but all 3 only set the first instance instead of themselves - Stack Overflow

programmeradmin16浏览0评论

I've got a Next.js component that I'm loading on a form 3 times, and passing a number to each one. The component is basically just a Input for a file. So I select an image, and then in theory should display that image in the component that picked it. But whatever image is picked in component 2 or 3, the image only shows in component 1. And I'm at a loss as to why. I recognise that I must be missing something really straightforward here. But I'm missing it. I've cut this code down to as minimal as possible to reproduce the issue.

Here is the Form:

"use client";

import FileSelector from "./file_selector";

export const SimpleForm = () => {
  return (
    <div className="flex flex-col gap-4">
      <div className="flex items-center justify-center gap-4 p-4">
        <FileSelector num="1" />
        <FileSelector num="2" />
        <FileSelector num="3" />
      </div>
    </div>
  );
};

Here is the component (file_selector):

"use client";

import React from "react";
import { ImgBox, ShowImg } from "./img_options";

const FileSelector = ({ num }: { num: string }) => {
  const [filePath, setFilePath] = React.useState<string>("");
  const [fileName, setFileName] = React.useState<string>("");

  const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (file) {
      console.log("file is ", file);
      const value = URL.createObjectURL(file);
      setFilePath(value);
      setFileName(file.name);
    }
  };

  return (
    <div>
      <input
        type="file"
        onChange={handleFileChange}
        className="hidden"
        id="file-selector"
      />
      <label htmlFor="file-selector" className="cursor-pointer">
{/* I had this div and the one below in separate components, but added them here for simplicity.  */}
        <div> 
          {filePath ? (
            <div>
              <img
                className="h-64 w-64 object-contain"
                src={filePath}
                alt={fileName}
              />
            </div>
          ) : (
            <div className="box-border flex h-64 w-64 items-center justify-center border-4 border-white p-4">
              <h1 className="text-2xl font-bold tracking-tight text-white">
                Image {num}
              </h1>
            </div>
          )}
        </div>
      </label>
    </div>
  );
};

export default FileSelector;

So, if I select an image with either Image 2 or Image 3, both of those set Image 1. Image 1 also sets Image 1. All 3 Image divs show the correct number.

I've got a Next.js component that I'm loading on a form 3 times, and passing a number to each one. The component is basically just a Input for a file. So I select an image, and then in theory should display that image in the component that picked it. But whatever image is picked in component 2 or 3, the image only shows in component 1. And I'm at a loss as to why. I recognise that I must be missing something really straightforward here. But I'm missing it. I've cut this code down to as minimal as possible to reproduce the issue.

Here is the Form:

"use client";

import FileSelector from "./file_selector";

export const SimpleForm = () => {
  return (
    <div className="flex flex-col gap-4">
      <div className="flex items-center justify-center gap-4 p-4">
        <FileSelector num="1" />
        <FileSelector num="2" />
        <FileSelector num="3" />
      </div>
    </div>
  );
};

Here is the component (file_selector):

"use client";

import React from "react";
import { ImgBox, ShowImg } from "./img_options";

const FileSelector = ({ num }: { num: string }) => {
  const [filePath, setFilePath] = React.useState<string>("");
  const [fileName, setFileName] = React.useState<string>("");

  const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (file) {
      console.log("file is ", file);
      const value = URL.createObjectURL(file);
      setFilePath(value);
      setFileName(file.name);
    }
  };

  return (
    <div>
      <input
        type="file"
        onChange={handleFileChange}
        className="hidden"
        id="file-selector"
      />
      <label htmlFor="file-selector" className="cursor-pointer">
{/* I had this div and the one below in separate components, but added them here for simplicity.  */}
        <div> 
          {filePath ? (
            <div>
              <img
                className="h-64 w-64 object-contain"
                src={filePath}
                alt={fileName}
              />
            </div>
          ) : (
            <div className="box-border flex h-64 w-64 items-center justify-center border-4 border-white p-4">
              <h1 className="text-2xl font-bold tracking-tight text-white">
                Image {num}
              </h1>
            </div>
          )}
        </div>
      </label>
    </div>
  );
};

export default FileSelector;

So, if I select an image with either Image 2 or Image 3, both of those set Image 1. Image 1 also sets Image 1. All 3 Image divs show the correct number.

Share Improve this question edited Feb 5 at 7:31 DarkBee 15.6k8 gold badges71 silver badges116 bronze badges asked Feb 5 at 5:52 PrimitivePrimitive 214 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 2

In this label:

<label htmlFor="file-selector" className="cursor-pointer">

You have same htmlFor attribute for each instance as a result its binding it with wrong input.

Solution: Make the htmlFor attribute unique so it binds with that specific instance like this:

<label htmlFor={`file-selector-${num}`} className="cursor-pointer">

This ensures that each label correctly binds to its corresponding file input, and images will be set accordingly.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论