18

I want to upload and read a file locally, but I want to do that using a custom button not using HTML input.

<input type="file" id="my_file_input" />

I found this way but I don't want to use this shape or this button, I wanted to use a material UI Raised Button to do this functionality to match the other site Button.

I also tried the following way but it didn't work because as i clicked the button nothing happened.

<input type="file" id="my_file_input" style={{display:"none"}}/>
<label htmlFor="my_file_input">
    <RaisedButton
        label="Import from Excel"
        labelColor="#FFFFFF"
        backgroundColor="#01579b"
        />
</label>

I thought I should do the uploading/reading file functionality manually in the onClick function of the RaisedButton but I didn't find a way to do that.

So is there any other solution for this problem in react?

3
  • You can do this with HTML/CSS: Replace input file with my own button in the form Commented Feb 13, 2019 at 15:04
  • @HereticMonkey it works in html but doesn't work in react. Commented Feb 13, 2019 at 15:13
  • 1
    Sure it does. The solution does not depend on JavaScript, and React is JavaScript. If you really can't get it working, edit your question to include a minimal reproducible example, showing how you implemented it and how it "doesn't work". You can use Stack Snippets to create a runnable snippet here on Stack Overflow. Commented Feb 13, 2019 at 15:18

4 Answers 4

18

I wanted to provide an update for using refs with functional components. Here is a quick example:

Import React, {useRef} from 'React'

const myComponent = () => {
  const fileInputRef = useRef();
  
  const handleChange = (event) =>{
    // do something with event data

  }
  
  return(
    <>
      <button onClick={()=>fileInputRef.current.click()}>
        Custom File Input Button
      </button>
      <input onChange={handleChange} multiple={false} ref={fileInputRef} type='file'hidden/>
    </>
  )
}

Sign up to request clarification or add additional context in comments.

1 Comment

you have errors in your code
9

I hope this code will help you. We can solve it in two ways.

1-)

HTML

<div>
<input type="file" hidden ref={this.inputReference} onChange={this.fileUploadInputChange} />
<button className="ui button" onClick={this.fileUploadAction}>
    Image Upload
</button>
{this.state.fileUploadState}
</div>

REACT CONSTRUCTOR

constructor(props) {
    super(props);
    this.state={fileUploadState:""}
    this.inputReference = React.createRef();
}

ONCLICK FUNCTION

fileUploadAction = () =>this.inputReference.current.click();
fileUploadInputChange = (e) =>this.setState({fileUploadState:e.target.value});

2-)

HTML

<div>
<input id="fileButton" type="file" hidden />
<button onClick={this.fileUploadButton}>
    Image Upload
</button>
{this.state.fileUploadState}
</div>

React State

this.state = {fileUploadState:""}

React Function

fileUploadButton = () => {
document.getElementById('fileButton').click();
document.getElementById('fileButton').onchange = () =>{      
this.setState({
    fileUploadState:document.getElementById('fileButton').value
        });
    }
}

Comments

2

please read API of React Material https://material-ui.com/demos/buttons/

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';

const styles = theme => ({
  button: {
    margin: theme.spacing.unit,
  },
  input: {
    display: 'none',
  },
});

function ContainedButtons(props) {
  const { classes } = props;
  return (
    <div>
      <input
        accept="image/*"
        className={classes.input}
        id="contained-button-file"
        multiple
        type="file"
      />
      <label htmlFor="contained-button-file">
        <Button variant="raised" component="span" className={classes.button}>
          Upload
        </Button>
      </label>
    </div>
  );
}

ContainedButtons.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(ContainedButtons);

1 Comment

I feel like there has to be a better way other than using a label as a button. I know sometimes it is hard to use semantic HTML in React depending on what you are trying to do, but it is good to try using semantic HTML where you can.
2

As the doc says, you just need to add:

component="span"

To the button component.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.