How to use ref for "input file" with react redux-form (controlled form)

572 Views Asked by At

I'm trying to refer an input file <Control.file /> element to another well styled element and even after googling I didn't find the answer so I'm here with all hope to get an answser.

This is a part of my redux controlled form and useRef hook:

  const fileInput = useRef(null);

    <Form model="testimonial" onSubmit={(value) => handleSubmit(value)}>                            
     <div id="preview-upload" className="form-group">
                                       
        <span onClick={() => {console.log(fileInput.current); fileInput.current.click()}} ></span>
                                        
        <Control.file ref={fileInput} onChange={(e) => handleImgPreview(e)} model=".photo" name="photo" id="photo" /> 
      </div>
    </Form>   

This is the function that onChange would be executed

const handleImgPreview = (event) =>{
    console.log(event)
    event.preventDefault();
    let reader = new FileReader();
    let file = event.target.files[0];

    reader.onloadend = () => {
        setImgPrev({...imgPrev, file: file, imgUrl: reader.result})
    }

    reader.readAsDataURL(file)
};

when I change to normal HTML input like <input type="file" ....... /> it works fine, but of course I got a problem when I submit the form and when I change it to <Control.file /> I got an error message says: TypeError: fileInput.current.click is not a function when I click on span element.

I tried

<span onClick={() => fileInput.current.props.onChange()}} />

then event became undefined:

TypeError: Cannot read property 'preventDefault' of undefined

console.log(event) // undefined

1

There are 1 best solutions below

0
Anis On

Instead of

ref={fileInput}

use

getRef={(input) => fileInput = input}

and notice getRef prop accept fuction which calls the callback provided to it with the node instance.

Now if you console fileInput you'll get thanks to the callback fuction inside getRef, therefore you won't have to access to .current, just call the click() method after iputFile as shown below:

<span onClick={() => {console.log(fileInput); fileInput.click()}}></span>
    
<Control.file getRef={(input) => fileInput = input} onChange={(e) => handleImgPreview(e)} model=".photo" name="photo" id="photo" /> 

For more information:

https://davidkpiano.github.io/react-redux-form/docs/api/Control.html