0

Hi I am very new to React.js and typescript.I am trying to upload a simple file along with simple inputs.

I examined some examples(ex1,ex2,ex3) related with file uploading or input element events on the web but I couldn't make any of them to work.

Here is my tsx file.

import * as React from 'react';
//import * as $ from "jquery";
import { RouteComponentProps } from 'react-router';
import { Button, Form, FormGroup, Label, Input, FormText } from 'reactstrap';
interface UploadContainerState {

    tcknVkn: number;
    proclamationYear: number;
    file: FileList|null;
}
export default class UploadContainer extends React.Component<{}, UploadContainerState> {
    constructor(props: any) {
        super(props);
        this.state = {
            proclamationYear: 0,
            tcknVkn: 0,
            file: null
        }
        this.proclamationYearChange = this.proclamationYearChange.bind(this);
        this.tcknVknChange = this.tcknVknChange.bind(this);
        this.uploadFile = this.uploadFile.bind(this);
        this.fileChange = this.fileChange.bind(this);

    }
    proclamationYearChange(event: any) {
        this.setState({ proclamationYear: event.target.value });
    }
    tcknVknChange(event: any) {
        this.setState({ tcknVkn: event.target.value });
    }
    fileChange(event: any) {
        this.setState({ file: event.target.files[0] });
    }

    render() {
        return (
            <div>

                <form className="uploader" encType="multipart/form-data" >
                    <br />
                    <FormGroup>
                        <Label for="proclamationYear">Beyanname Yılı</Label>
                        <Input type="text" name="proclamationYear" id="proclamationYear" placeholder="Beyanname Yılını Giriniz." onChange={this.proclamationYearChange} value={this.state.proclamationYear} />
                    </FormGroup>
                    <FormGroup>
                        <Label for="tcknVkn">Tckn/Vkn</Label>
                        <Input type="text" name="tcknVkn" id="tcknVkn" placeholder="Tckn/Vkn Giriniz." onChange={this.tcknVknChange} value={this.state.tcknVkn} />
                    </FormGroup>

                    <input  type="file" name="file" className="upload-file" onChange={this.fileChange} value={this.state.file} />
                    <input type="button"  value="Beyanname Yükle" onClick={this.uploadFile} />
                </form>
            </div>
        );
    }
    uploadFile(event: any) {
        event.preventDefault();
        let formData = new FormData();
        formData.append('file', event.target.myimage.files[0]);
        formData.append('tcknVkn', event.target.tcknVkn.value);
        formData.append('proclamationYear', event.target.proclamationYear.value);
        fetch('ProposalData/UploadFile', {
            method: 'POST',
            credentials: 'include',
            headers: {
                'Content-Type': 'multipart/form-data',
                'Accept': 'application/json'
            },
            body: formData
        })
    }
};

I am receiving following error.

ERROR in [at-loader] ./ClientApp/components/UploadContainer.tsx:50:29 
    TS2322: Type '{ type: "file"; name: "file"; className: "upload-file"; onChange: (event: any) => void; value: Fi...' is not assignable to type 'DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>'.
  Type '{ type: "file"; name: "file"; className: "upload-file"; onChange: (event: any) => void; value: Fi...' is not assignable to type 'InputHTMLAttributes<HTMLInputElement>'.
    Types of property 'value' are incompatible.
      Type 'FileList | null' is not assignable to type 'string | number | string[] | undefined'.
        Type 'null' is not assignable to type 'string | number | string[] | undefined'.

Here is my typescript version 5.6.0

I can't understand how can such easy task becomes a nightmare.

2 Answers 2

2

I know this is not the optimal solution.But here is complete back-end and front-end code for those who are trying to accomplish same task using .net core,react.js and typescript.

Here is my tsx file note that I commented file property in my interface and made it public property.

import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import { Button, Form, FormGroup, Label, Input, FormText } from 'reactstrap';
import ListGroup from 'reactstrap/lib/ListGroup';

interface UploadContainerState {

    tcknVkn: number;
    proclamationYear: number;
    alertVisible: boolean;

    //file: FileList
}
export default class UploadContainer extends React.Component<{}, UploadContainerState> {
    public file: File;
    constructor(props: any) {
        super(props);
        this.state = {
            proclamationYear: 0,
            tcknVkn: 0,
            alertVisible: false
        }
        this.proclamationYearChange = this.proclamationYearChange.bind(this);
        this.tcknVknChange = this.tcknVknChange.bind(this);
        this.uploadFile = this.uploadFile.bind(this);
        this.fileChange = this.fileChange.bind(this);

    }
    proclamationYearChange(event: any) {
        this.setState({ proclamationYear: event.target.value });
    }
    tcknVknChange(event: any) {
        this.setState({ tcknVkn: event.target.value });
    }
    onDismiss() {
        this.setState({ alertVisible: false });
    }

    fileChange(event: any) {
        this.file = event.target.files[0];
        event.preventDefault();

    }

    render() {
        return (
            <div>

                <form onSubmit={this.uploadFile} className="uploader" encType="multipart/form-data" >
                    <FormGroup>
                        <Label for="proclamationYear">Year</Label>
                        <Input type="text" name="proclamationYear" id="proclamationYear"  onChange={this.proclamationYearChange} value={this.state.proclamationYear} />
                    </FormGroup>
                    <FormGroup>
                        <Label for="tcknVkn">Tckn/Vkn</Label>
                        <Input type="text" name="tcknVkn" id="tcknVkn"  onChange={this.tcknVknChange} value={this.state.tcknVkn} />
                    </FormGroup>

                    <input type="file" name="file" accept=".pdf" className="upload-file" onChange={this.fileChange} />
                    <input type="submit" value="Submit" />
                </form>
            </div>
        );
    }
    uploadFile(event: any) {
        let that = this;
        event.preventDefault();
        let formData = new FormData();
        formData.append('file', this.file);
        formData.append('tcknVkn', event.target.tcknVkn.value);
        formData.append('proclamationYear', event.target.proclamationYear.value);
        fetch("ProposalData/UploadFile", {
            method: 'POST',
            credentials: 'include',
            headers: {
                'Accept': 'application/json, */*',
            },
            body: formData
        })
            .then(handleErrors)
            .then(function (response) {
                console.log("ok");
            }).catch(function (error) {

                console.log(error);
            });
    }
};
function handleErrors(response: any) {
    if (!response.ok) {
        throw Error(response.statusText);
    }
    return response;
}

Here is my controller

public class FileUploadModel
{
    public string ProclamationYear { get; set; }
    public string TcknVkn { get; set; }
    public IFormFile File { get; set; }
}
 [HttpPost]
        public async Task<IActionResult> UploadFile([FromForm]FileUploadModel vm)
        {
            var file = vm.File;
Sign up to request clarification or add additional context in comments.

Comments

1

You have a mismatch in value property type. Expected is string | number | string[] | undefined while you are passing in FileList

You cannot set value of file input due to security reason. The only way to set file input's value is via user action in browser. Remove value={this.state.file} and it will compile.

Besides that, the type of the state field should be File

3 Comments

I removed value={this.state.file} and changed file type to string UploadContainerState { file: string; } and assign empty string to file: this.state = { file: '' } this time code compiles but I hit submit button this error appears. UploadContainer.tsx:59 Uncaught TypeError: Cannot read property 'files' of undefined What should be the type of file ?
Change the state field type to File
But this time you can't assign it null

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.