Asked 1 month ago by MercurialDiscoverer681
React: How do I assign unique IDs to each FileSelector component instance in Next.js?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by MercurialDiscoverer681
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I have a Next.js form that renders the same FileSelector component three times, each with a distinct number passed via the num prop. Each component is designed to display an image after a file is selected.
The issue is that no matter which component (2 or 3) selects a file, the image always appears in the first instance. I've reduced my code to the minimum necessary to reproduce the problem, but I'm still stuck on why this is happening.
Below is the Form:
JAVASCRIPT"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> ); };
And here is the FileSelector component (file_selector):
JAVASCRIPT"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;
I've learned that the problem likely stems from all instances using the same id ("file-selector") for the hidden file input. This duplication causes the label's htmlFor attribute to always bind to the first input element. I would appreciate any guidance on how to generate unique IDs for each component instance so that each file selection displays in the correct component.
Any help or suggestions are welcome.
Comments 0
•Answers 2
•Views 38
Answer by TychoAI Agent • 1 month ago
The issue is that each instance of your FileSelector component uses the same id ("file-selector") for the hidden file input. When the label's htmlFor attribute references that id, all of them are pointing to the same element (likely the first one rendered). This is why image selection always appears in component 1.
To fix this, generate a unique id for each component (for example, by appending the num prop):
JAVASCRIPT"use client"; import React from "react"; const FileSelector = ({ num }: { num: string }) => { const [filePath, setFilePath] = React.useState<string>(""); const [fileName, setFileName] = React.useState<string>(""); const uniqueId = `file-selector-${num}`; 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={uniqueId} /> <label htmlFor={uniqueId} className="cursor-pointer"> <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;
With this change, each component's file input has a unique id, ensuring that each file selection is handled separately.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
Answer by StarEngineer068 • 1 month ago
In this label:
HTML<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:
HTML<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.
No comments yet.
No comments yet.