Issue
I just started with TypeScript, so please bear in mind. I am trying to implement a simple file upload in React/TS. In general, I don't think I understand how to initialize objects, like in useState, and handle the possibilities properly. For example, consider this code where I am running a function when a user clicks an Upload button and I try to read the file from state and put in the formData to send it to my api endpoint):
const [fileSelected, setFileSelected] = React.useState<File>() // also tried <string | Blob>
const handleImageChange = function (e: React.ChangeEvent<HTMLInputElement>) {
const fileList = e.target.files;
if (!fileList) return;
setFileSelected(fileList[0]);
};
const uploadFile = function (e: React.MouseEvent<HTMLSpanElement, MouseEvent>) {
const formData = new FormData();
formData.append("image", fileSelected, fileSelected.name);
// line above ^ gives me the error below
};
}
Argument of type 'string | Blob | undefined' is not assignable to parameter of type 'string | Blob'. Type 'undefined' is not assignable to type 'string | Blob'.ts(2345)
How are you supposed to initialize your objects in useState? And if you don't initialize, like here, do you have to keep checking for null to keep the compiler happy? I just added a check in UploadFile to see if fileSelected is null. But then I had to do it again to reference fileSelected.name.
So for objects, particularly something like this File type, how should you handle initializing it? But also, in general, how to handle object types?
Not that it matters, but here's the markup part:
<Container className={classes.container}>
<label htmlFor="photo">
<input
accept="image/*"
style={{ display: "none" }}
id="photo"
name="photo"
type="file"
multiple={false}
onChange={handleImageChange}
/>
<Button
className={classes.buttons}
component="span"
variant="contained"
onClick={uploadFile}
>
Choose Picture
</Button>
</label>
</Container>
Solution
When you call useState
without setting an initial/default value then the type will include undefined
in addition to the expected type. Here you've used the generic <File>
to tell useState
what type to expect. But because you initiated it without setting a value, the type of fileSelected
becomes File | undefined
.
This is fine because it accurately represents the reality that there will not always be a File
object in the state. But it does mean that we have to check the value of fileSelected
before using it. Just add an if
statement and your formData.append()
call won't have any issues at runtime or in the typescript compiler. The interface File
extends Blob
so there is no issue assigning it to string | Blob
after we've ruled out the possibility of undefined
.
const uploadFile = function (e: React.MouseEvent<HTMLSpanElement, MouseEvent>) {
if (fileSelected) {
const formData = new FormData();
formData.append("image", fileSelected, fileSelected.name);
}
};
Answered By - Linda Paiste
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.