0

I am newbie on react. I have asked few days back regarding the upload on image by modifying the button through some div. I have thought to do it by hooks (based on my research)

One of the user has suggested me that use the label and on the use the htmlFor attribute with using the same id used on the input types file.

I have used but the problem is that on my image filed in the state where i am using to store the base64 uploaded string was wiped out through some kind of event bubbling or some other reason. On final submit, I did not get the image on state.

I have found that using Label will make some bubbling and my image in state will be refreshed with default value

This is my implementation:

constructor(props, context) {
    super(props, context);
}

postQuery=()=> {
 // This function trigger when final submit button is clicked and here i am not getting
 the image key with value in state.
 console.log('Final State: ', this.state); // Here i need the image in state
 // Other task is dependent on this.state.image; // ---> base64 string;
}

uploadImage()=> {
 // here I am getting the file which is selected by the user from frontend.
 // some function which return the image base64 string
 let fileToLoad = e.target.files[0]
 // here call the base64 function which is returning the base64 string
 this.setState({
   image: fileToLoad.base64,
 }, ()=> { console.log(this.state.image) }); // here I am getting the image key with base64 string on state.
}

render() {
 <div>
   <Button onClick={()=>this.postQuery()}>SUBMIT</Button>
 </div>
 <div>
   <FormControl
     id="formControlsFile"
     type="file"
     label="file"
     onChange={(e) => this.uploadImage(e)}
     style={{display: 'none'}} // if change to display block and click on the input then everything works correct.
   />
   <label style={{ display: 'inline-block' }} htmlFor="formControlsFile">
      <i
        className={cx(
         fontStyles.fa,
         fontStyles["fa-image"]
        )}
       />
       <span>UPLOAD IMAGE</span>
   </label>
 </div>
}

Can anyone guide me where I need to fix/modify. Any suggestion or help is highly appreciated. Thanks in advance for the interactions.

Aks
  • 1,092
  • 3
  • 12
  • 29
  • Do not use `display: none` to hide the input field, some browsers will make it non-interactive then. Use a combination of opacity, limited width/height (min. 1px, do not use 0, that can cause similar problems) and `overflow:hidden`, and absolute positioning (if necessary) - https://stackoverflow.com/a/7691323/1427878 – CBroe May 23 '22 at 12:50
  • @CBroe that did not solve the problems as if it is display block then also if I click on div rather than click on input type file then also I am not getting the image. – Aks May 23 '22 at 12:56
  • @CBroe anyways thanks for interacting. According to me it is some kind of event bubbling. Have tried event.stopPropogation() but not getting luck. Also tried on componentDidUpdate(), after clicking on submit button, not getting the image and then getting the image as it is called multiple times. Not sure where I have done wrong or need to add more piece of code – Aks May 23 '22 at 12:59
  • Can you check what the event target is inside `uploadImage` in each case? – CBroe May 25 '22 at 08:34
  • @CBroe I have update the question in uploadImage Function – Aks May 25 '22 at 09:51

1 Answers1

0

What worked for me using material-UI was this piece of code

             const [mainImage, setMainImage] = useState(null);
             const handleCapture = ({ target }) => {
              setMainImage(target.files[0]);
              uploadImage("main", target.files[0]);
             };

            <Button
              variant="contained"
              component="label"
              sx={{ width: "100%" }}
            >
              Upload Image
              <input
                hidden
                id="faceImage"
                type="file"
                // multiple
                accept="image/*"
                onChange={handleCapture}
              />
            </Button>
Satyam Saurabh
  • 488
  • 4
  • 16