Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix Failed to set the 'value' property on 'HTMLInputElement' for react?

I am working on Nextjs and try to upload a single file. Every time I attach new file, then I get this error at the console log.

At the console, I see this error:

Warning: A component is changing an uncontrolled input of type file to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.

Then, the second one is:

react-dom.development.js:2592 Uncaught DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.

Here is my sample code:

  1. HTML path at render function
<div className="form-group">
  <label htmlFor="p_file">Image</label>
  <input
    id="p_file"
    type="file"
    className="form-control-file"
    value={formData.image}
    onChange={ e => onChangeImage(e)} />
</div>
  1. Javascript path
const [formData, setFormData] = useState({
  ...,
  image: undefined
});

const onChangeImage = event => {
  console.log(event.target.files[0]);
  setFormData( prev => ({
    ...prev,
    image: event.target.files[0]
  }));
}
like image 731
Tran Son Hoang Avatar asked Feb 24 '20 05:02

Tran Son Hoang


2 Answers

From the React documentation on uncontrolled elements:

In React, an <input type="file" /> is always an uncontrolled component because its value can only be set by a user, and not programmatically.

This is a security feature, to ensure that you can not pull data from a users disk without them specifically choosing to do so.

To me, it seems like this isn't what you're trying to do. All you want to do is display the name of the selected file. You can do that by creating your own label and button, with a hidden file element. When you click your custom button, call the click event imperatively on the HTMLFileInput. Register your change event on the file input, and update your custom element with the response.

like image 152
James Hay Avatar answered Oct 23 '22 18:10

James Hay


If you want to fire the onChange event each time you select a file (regardless of whether it is the same file or a different one) you could set value={''} in your input. This will empty the input every time it is rendered.

I drew inspiration for this answer from chrisv here:

React controlled component input value with empty string

See example below:

import * as React from "react";
import {useEffect, useState} from "react";

const FileComponentTest = () => {
  const [file, setFile] = useState(null);

  useEffect(() => {
    console.log("File has been set.")
  },[file]);

  return (
    <React.Fragment>
      <input
        type="file"
        onChange= {(e) => setFile(e.target.files[0])}
        value ={""}
      />
    </React.Fragment>
  )
};

I get no errors in the console with this.

Update:

Please see link to fiddle below:

https://jsfiddle.net/geoj12/tjbvpyzs/11/

like image 30
Mr. J Avatar answered Oct 23 '22 20:10

Mr. J