I would like to run the following code to have the file selector input a file and manage the input file as a state in the file. But it produces output as described in the comments. I do not know the cause. How should I fix the problem?
const [file, setFile] = useState<File | null>(null);
const fileSelect = (event: ReactChangeEvent<HTMLInputElement>) => {
if (event.target.files === null) { return ; }
const f: File | null = event.target.files[0];
console.log(typeof(f)); // <- object
setFile(f);
console.log(f); // <- null
}
return (
<div className="flex px-1">
<input
onChange={fileSelect}
type="file"
/>
</div>
);
2
Answers
This is because when you call setState it doesn’t mutate the state immediately. You can refer to this thread here.
Why does calling react setState method not mutate the state immediately?
Based on your Typescript data types, it appears you want to save the actual file contents into state, not just the name of the file.
These lines in your code:
…show an attempt to update state with type
File
, not typestring
.Saving file contents into state can be achieved with React.useState. File contents can be converted to Base64 and stored in state as strings.
These demos on JS Fiddle use React.useState and Redux Toolkit. Source code is available on SourceHut: React.useState; Redux Toolkit.
The demos use the FileReader: readAsDataURL() method to upload files as Data URLs which can be saved as strings (not strictly as File types) in an array using React.useState.
These functions are the key to saving file content:
Read the file as a Data URL and update state
Event handler for file upload field