Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Input type="file" showing weird behavior when used along with another input type

I have an input type="file" and an input type="text". When I choose the file first and then put text in the input box and click the Add button, the picture doesn't show but when I put the text first and then choose the picture (file), it behaves normally.I think there's some problem in the inputKey That I have given. Here's a link from where I found this method http://robhoffmann.me/2016/03/12/Clearing-a-file-input-in-React/

What I am trying to do: I want to be able to choose an Image and type a product name which will then show on the screen. As soon as I click the Add button. I want both the inputs i.e. file type and text type to reset so that I can add the picture and Name of next product and so on..

function Admin(props){

    const [productName, setproductName] = React.useState("");

    let [productPicture, setproductPicture] = React.useState({file:null,inputKey:Date.now()});


    return (
        <div>
            <Link to="/">Go back</Link><br/><br/>
            <input type="file" onChange={(e)=>(productPicture=URL.createObjectURL(e.target.files[0]))} key={productPicture.inputKey}></input><br/>
            <input type="text" required placeholder="Product Name" onChange={(e)=>setproductName(e.target.value)} value={productName}></input><br/><br/>

<button type="Submit" onClick={(e)=>{props.AddInfo({productName,productPicture});setproductName("");setproductPicture({file:null,inputKey:Date.now()})}}>Add</button>
            <br/><br/>

            <div>
             {props.products.map((x)=>(<div>{x.name} {typeof x.picture === 'string' ? <img src={x.picture} alt="Product Picture" style={{width:"250px"}}></img>:""} </div>))}   
            </div>
        </div>
    )
}

export default Admin;

I expect the output to show the productName and productPicture when I click Add button but this only happens when I type in the text first and then choose the image/file and NOT when I do the vice-versa.

like image 535
Hardik Aswal Avatar asked Nov 07 '22 14:11

Hardik Aswal


1 Answers

By doing this,

<input type="file" onChange={(e)=>(productPicture=URL.createObjectURL(e.target.files[0]))} key={productPicture.inputKey}></input><br/>

You are directly trying to mutate the state, productPicture=URL.createObjectURL(e.target.files[0]) which is wrong. Here you are not setting state. To set actual state you need to make use of setproductPicture setter function.

<input type="file" onChange={setImage} key={productPicture.inputKey} />

And setImage function should be,

const setImage = (e) => {
  console.log(e.target.files[0].name);
  let file = e.target.files[0];  //Capture the file in variable otherwise event gets nullified and you won't get file.
  setproductPicture(prevState=>({
     ...prevState,
     file: URL.createObjectURL(file)
  }))
}

Demo

Note: input is an empty tag, don't close it like <input></input>. You can just do this, <input />.

like image 169
ravibagul91 Avatar answered Nov 14 '22 21:11

ravibagul91