Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reactjs: problem converting <input type="file"> to custom button icon

I am new to React and trying to build an application where I want to press a custom button which will open a file dialog and upload a file on selecting it. Here is my code:

class ComposeButtons extends Component{

    constructor(props) {
        super(props);
        this.state={
            selectedFile: null
        };
        this.myInput = React.createRef();
    }

    fileSelectedHandler = (event) => {
        console.log(event.target.files[0]);
        this.setState({
            selectedFile: event.target.files[0]
        })
    };
    triggerClick = () => {
        this.myInput.current.click()
    };

    fileUploadHandler = () => {
      /* file upload triggered */
      console.log('file upload triggered');
    };

    render() {
        return(
            <div className={"composeForm-area"}>
                <div>
                    <Input
                        style={{display:'none'}}
                        type={"file"}
                        onChange={this.fileSelectedHandler}
                        ref={this.myInput}
                    />
                    <Button onClick={this.triggerClick}
                            onChange={this.fileUploadHandler} 
                            style={{ backgroundColor: '#DDDCDC'}}>
                        <Icon style={{ fontSize: '20px'}} type="camera" />
                    </Button>
                </div>
            </div>
        )
    }
}
export default ComposeButtons;

My current output:

enter image description here

I only get a clickable icon like above, however, upon clicking it throws:

Uncaught TypeError: _this.myInput.current.click is not a function
    at eval (ComposeButtons.js:88)
    at Button._this.handleClick (button.js:143)
    at HTMLUnknownElement.callCallback (react-dom.development.js:14

What I want:

I simply want to open a file dialog to select file when i click this camera button and after i select and press ok in file dialog, it should close and trigger fileUploadHandler function printing the message on the console. That's all!

What I tried:

Apart from code above I tried to replace code inside div in render method with this code:

        <div>
            <Input
                id="myInput"
                style={{display:'none'}}
                type={"file"}
                onChange={this.fileSelectedHandler}
                ref={(ref) => this.myInput = ref}
            />
            <Button onClick={(e) => this.myInput.click() }
                    style={{ backgroundColor: '#DDDCDC'}}>
                <Icon style={{ fontSize: '20px'}} type="camera" />
            </Button>
        </div>

I also followed almost all the answers on stackoverflow but nothing seems to working for me. It will be really helpful if someone can point me in right direction.

This is my first hobby project in React.

like image 459
Dhruvsito Avatar asked Dec 18 '22 16:12

Dhruvsito


1 Answers

As far as I got your question. All we can do is add a label tag referring to the input type file using the for attribute in the label tag. By doing this we don't need to use ref

For info in this link.

Now all that needed to be done is to write appropriate css for the label tag

<div>
  <label htmlFor="myInput"><Icon style={{ fontSize: '20px'}} type="camera" /></label>
  <input
    id="myInput"
    style={{display:'none'}}
    type={"file"}
    onChange={this.fileSelectedHandler}
  />
</div>

After that, to trigger file upload. we can call fileUploadHandler after fileSelectedHandler is called.

fileSelectedHandler = (event) => {
  console.log(event.target.files[0]);
  this.setState({
      selectedFile: event.target.files[0]
  }, () => this.fileUploadHandler());
};
like image 111
raman Avatar answered Dec 31 '22 02:12

raman