Skip to content
Advertisement

Defining type for input file state: React+Typescript

I am getting the following error while I define the type of file object inside state, Argument of type 'null' is not assignable to parameter of type 'File | (() => File)'.ts. I am having a upload component, that basically takes care of selecting the file and sending its value to the parent component. I am trying to this in a typescript way and I am unable to get rid of this.

Link to the sandbox: https://codesandbox.io/s/react-hook-upload-oxqdp2?file=/src/Upload.tsx

Upload

import * as React from "react";
import { Button } from "@material-ui/core";
import { useState } from "react";

interface UploaderProps {
  fileType?: string | AcceptedFileType[];
}

enum AcceptedFileType {
  Text = ".txt",
  Gif = ".gif",
  Jpeg = ".jpg",
  Png = ".png",
  Doc = ".doc",
  AllImages = "image/*",
  AllVideos = "video/*",
  AllAudios = "audio/*"
}

export const Upload = (props: UploaderProps): JSX.Element => {
  const { fileType } = props;
  const acceptedFormats: string | AcceptedFileType[] =
    typeof fileType === "string"
      ? fileType
      : Array.isArray(fileType)
      ? fileType?.join(",")
      : AcceptedFileType.Text;
  const [selectedFiles, setSelectedFiles] = useState<File>(null);

  const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
    setSelectedFiles(event?.target?.files?.[0]);
  };

  const onUpload = () => {
    // eslint-disable-next-line no-console
    console.log(selectedFiles);
  };

  return (
    <>
      <Button
        variant="contained"
        component="label"
        style={{ textTransform: "none" }}
      >
        <input
          hidden
          type="file"
          accept={acceptedFormats}
          onChange={handleFileSelect}
        />
        <span> Choose file to upload</span>
      </Button>
      <Button
        color="primary"
        disabled={!selectedFiles}
        style={{ textTransform: "none" }}
        onClick={onUpload}
      >
        Upload
      </Button>
    </>
  );
};

Can someone help?

Advertisement

Answer

You should probably stick to undefined:

const [selectedFiles, setSelectedFiles] = useState<File | undefined>(undefined);

const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
  setSelectedFiles(event?.target?.files?.[0]);
};

This is because when you set it, the value has the type File | undefined.

This will also force you to check the value before using it, since it could be undefined.

If you know that there will be a file, you can use an assertion with !:

setSelectedFiles(event?.target?.files?.[0]!);

and maybe keep the type as File | null, but even then I’d still use File | undefined because null is a bit quirky in JavaScript (typeof null === "object').

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement