React hook changing the state variable of wrong component when file input

Codesandbox : https://codesandbox.io/s/vigilant-elgamal-dciqs

When I input an image and try to display its preview on the same container, only the image in the first container updates i.e setImage changes the value of photo for only the first component. How do I fix this?

App.js

import { useState } from "react";
import "./styles.css";
import InputContainer from './InputContainer'
export default function App() {
const [inputArr,setInputArr] = useState([])
const addInputContainer=()=>{
setInputArr([...inputArr,''])
}
return (
 <div className="App">
  <button onClick={addInputContainer}>Add Input-Container</button><br/>
  {inputArr.map((input,index)=>{
    return <InputContainer key={index}/>
  })}
  
 </div>
 ); 
}

InputContainer.jsx

import { useState } from "react";

const InputContainer = () => {
  const [image, setImage] = useState("");
  const handleClick = () => {
    document.querySelector(".input-image").click();
  };
  const handleInput = (e) => {
    const selected = e.target.files[0];
    if (!selected) return;
    let reader = new FileReader();
    reader.readAsDataURL(selected);

    reader.onload = () => {
      setImage(reader.result);
    };
  };
  return (
    <div className="input-container" onClick={handleClick}>
      {image ? <img src={image} className="image" /> : "Click For input"}
      <input
        type="file"
        onChange={handleInput}
        className="input-image"
        style={{ display: "none" }}
      />
    </div>
  );
};
export default InputContainer;

Answer

All the components has same fixed class name "input-image". As you are querying with class name on image click it is taking the first one and updating the image there.

I have modified your code, tried in sandbox – https://codesandbox.io/s/charming-cdn-vh5xv

I’m passing 1 extra props to InputContainer and this prop is dynamic taking the index of array. Then I’m using the in the id field of the input tag and querying using this id document.querySelector(`#${imgName}`).click();

App.js

import { useState } from "react";
import "./styles.css";
import InputContainer from "./InputContainer";
export default function App() {
  const [inputArr, setInputArr] = useState([]);
  const addInputContainer = () => {
    setInputArr([...inputArr, ""]);
  };
  return (
    <div className="App">
      <button onClick={addInputContainer}>Add Input-Container</button>
      <br />
      {inputArr.map((input, index) => {
        return <InputContainer key={index} imgName={`img-${index}`} />;
      })}
    </div>
  );
}

InputContainer.jsx

import { useState } from "react";

const InputContainer = ({ imgName }) => {
  const [image, setImage] = useState("");
  const handleClick = () => {
    document.querySelector(`#${imgName}`).click();
  };
  const handleInput = (e) => {
    const selected = e.target.files[0];
    if (!selected) return;
    let reader = new FileReader();
    reader.readAsDataURL(selected);

    reader.onload = () => {
      setImage(reader.result);
    };
  };
  return (
    <div className="input-container" onClick={handleClick}>
      {image ? <img src={image} className="image" /> : "Click For input"}
      <input
        type="file"
        onChange={handleInput}
        className="input-image"
        id={imgName}
        style={{ display: "none" }}
      />
    </div>
  );
};
export default InputContainer;