Search code examples
javascriptreactjsaxiossemantic-ui-react

Upload 2 files within a form in ReactJS


I am getting 3 errors:

1.

 VM1307:3 Uncaught TypeError: Cannot read property '_avast_submit' of undefined
    at <anonymous>:3:28
    at <anonymous>:32:19

2.

POST http://127.0.0.1:8000/api/materials 422 (Unprocessable Entity)

3.

createError.js:16 Uncaught (in promise) Error: Request failed with status code 422
at createError (createError.js:16)
at settle (settle.js:18)
at XMLHttpRequest.handleLoad (xhr.js:77)

This is what my webpage looks like

enter image description here

and this is my code:

import React, { Component } from 'react';
import axios from 'axios';
import { Form,  TextArea, Button, Grid, Segment, Header } from 'semantic-ui-react'

class UploadScreen extends Component {
    constructor(){
        super();
        this.state={
          title:'',
          tags:'',
          description: '',
          viewing_time: '',
          file: null,
          preview: null,
          url: '',
          errors: {}
        }
       }

    fileChangedHandler = (event) => {
        this.setState({file: event.target.files[0]})
    }

    previewChangedHandler = (event) => {
        this.setState({preview: event.target.files[0]})
    }

    onChange = (e) => {
        this.setState({ [e.target.name]: e.target.value });
       }

    onSubmit = (e) => {
        const formData = new FormData()
        formData.append('file', this.state.file, this.state.file.name)
        const previewData = new FormData()
        previewData.append('preview', this.state.preview, this.state.preview.name)

        var token = localStorage.getItem('jwt');
        var apiBaseUrl = "http://127.0.0.1:8000/api/materials";
        var payload={
            "title":this.state.title,
            "tags":this.state.tags,
            "description":this.state.description,
            "viewing_time":this.state.viewing_time,
            "url":this.state.url
        }
        var config = {
          headers: {
            'Authorization': "bearer " + token,
            'Accept': 'application/json',
            'Content-Type': 'application/json',
          },
          withCredentials: false
        }

        axios.post(apiBaseUrl, payload, formData, previewData, config)
        .then(function (response) {
          console.log(response);
          if(response.status == 200){
              console.log("success");
          }
          else if(response.status == 204){
              console.log("nope");
          }
          else{
              console.log("nope nope");
          }
      })
      }

    render() {
        const { title, tags, description, viewing_time, file, preview, url, errors } = this.state;
        return (
            <Grid textAlign='center' style={{ height: '100%' }} verticalAlign='middle'>
            <Grid.Column style={{ maxWidth: 1000 }}>
            <br />
            <br />
            <br />
            <Header as='h1'>Create a New Material</Header>
            <Form onSubmit={this.onSubmit}>
                <Segment stacked>
            <Header as='h2' textAlign='left'>Details</Header>
            <Form.Input
            type='text'
            name='title'
            value={title}
            onChange={this.onChange}            
            placeholder='Title' 
            fluid
            icon='pencil'
            iconPosition='left' 
            />

            <Form.Group widths='equal'>
              <Form.Input
                type='text'
                name='viewing_time'
                value={viewing_time}
                onChange={this.onChange}    
                placeholder='Viewing Time'
                fluid
                icon='clock'
                iconPosition='left'
              />
              <Form.Input
                type='text'
                name='tags'
                value={tags}
                onChange={this.onChange}                
                placeholder='Tags (multiple tags must be separated by semi-colon)'
                fluid
                icon='tags'
                iconPosition='left'
              />
            </Form.Group>
            <Form>
            <TextArea
                name='description'
                value={description}
                onChange={this.onChange}     
                autoHeight 
                placeholder='Description' 
                fluid
            />
            </Form>
            <Header as='h2' textAlign='left'>Material Upload</Header>
            <Form>
                <input type="file" class="form-control-file" id="file" name='file' onChange={this.fileChangedHandler}  aria-describedby="fileHelp" />
            <Header as='h3'>or</Header>
            <Form.Input
                name='url'
                value={url}
                onChange={this.onChange}  
                placeholder='File URL'
                fluid
                icon='world'
                iconPosition='left'
              />
            </Form>
            <Header as='h2' textAlign='left'>Material Preview</Header>
            <Form>
                <input type="file" class="form-control-file" id="preview" name='preview' onChange={this.previewChangedHandler} aria-describedby="fileHelp" />
            </Form>
            <br />
            <Button fluid size='large' type="submit">
                Create
            </Button>
            </Segment>
          </Form>
          </Grid.Column>
          </Grid>
        );
    }
}
export default UploadScreen;

I just used what the tutorials did with uploading pictures but it's giving me errors. I want to upload, two different files, one pdf and one image to the axios request as a part of the form. What am I possibly doing wrong here?


Solution

  • You only need one FormData instance, and then you need to append all fields (both files and each other input that you want to post) to that one instance.

    Then in Axios you just send axios({... , data: data})

    Esit - typos im on Ipad, sorry if it’s hard to read but it’s harder to type 😂