0

I am learning reactjs for building web application. Basically, my goal is I want to create reactjs component that can upload local csv file to the server (I created server js). To do so, I come across a basic reactjs component implementation down below:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  var FormBox = React.createClass({
    getInitialState: function () {
      return {
        file: '',
        FilePreviewUrl: ''
      };
    },
    pressButton: function () {
      e.preventDefault();
      console.log('handle uploading-', this.state.file);
    },
    uploadCSV: function (e) {
      e.preventDefault();
      let reader = new FileReader();
      let file = e.target.files[0];

      reader.onloadend = () => {
        this.setState({
          file: file,
          FilePreviewUrl: reader.result
        });
      }
      reader.readAsDataURL(file);
    },
    render: function () {
      let {FilePreviewUrl} = this.state;
      let FilePreview = null;
      if (FilePreviewUrl) {
        FilePreview = (<img src={FilePreviewUrl} />);
      } else {
        FilePreview = (<div className="previewText">Please select an Json for Preview</div>);
      }
      return (
        <div>
        <form action='.' enctype="multipart/form-data">
          <input type='file'  onChange={this.uploadCSV}/>
          <button onClick={this.pressButton}> Get it </button>
        </form>
        <div className="filePreview">
          {FilePreview}
        </div>
        </div>
      )
    }
  })
}
ReactDOM.render(<FormBox />, document.getElementById('root'))
export default App;

but when I run my component I got an error which is not intuitive to me. Here is the error:

Failed to compile.

./src/App.js
  Line 6:  Parsing error: Unexpected token

  4 | 
  5 | class App extends Component {
> 6 |   var FormBox = React.createClass({
    |       ^
  7 |     getInitialState: function () {
  8 |       return {
  9 |         file: '',

How to fix this error? How to make above implementation works for the purpose of uploading csv file to the server? any idea?

clarification:

I am doing this because I intend to upload local csv file to the server and trigger API key that provided at back-end to populate the csv data to the database. I am newbie to reactjs so my above code may not be well shaped. can anyone help me how to make this works? any help would be appreciated.

goal:

Sine few smart people in SO community suggested me that I was wrong about the implementation. What I am actually trying to do is to upload local files to server. How can I modify above code for creating reactjs component for uploading file to server?

beyond_inifinity
  • 443
  • 13
  • 29
  • 1
    Remove the `class App extends Component` around your `var`. Or better: convert the `FormBox` into a `Component` using the newer class syntax. – lumio Apr 08 '19 at 15:26
  • @lumio would you able to elaborate your point with fully working solution? I am a newbie to `reactjs` so I may not quite follow what you said. Thanks – beyond_inifinity Apr 08 '19 at 15:28
  • You do not need `React.createClass` at all, which tutorial are you following? Also, your `uploadCSV` is misnamed since it is not concerned with uploading anything. –  Apr 08 '19 at 15:30
  • @ChrisG I followed youtube tutorial then try this [file uploading](https://stackoverflow.com/questions/39695275/react-js-handling-file-upload)? do you have any solid idea? Thanks in advance – beyond_inifinity Apr 08 '19 at 15:33
  • @lumio are you able to run your code on reactjs app? Because it gives me still same error. Is your code testable with `npm start`? – beyond_inifinity Apr 08 '19 at 15:35
  • Not meant in a bad way, knowing you are still learning and every beginning is hard: But maybe it is wise to take a step back and learn the syntactical differences between declaring a `class` and a `variable`. – lumio Apr 08 '19 at 15:35
  • What you have implemented from that other answer is an in-browser preview of the selected file; that has nothing to do with an actual file upload (which is a POST request to the server). Again, which tutorial? Are they combining `class` and `React.createClass` like that? I doubt it. –  Apr 08 '19 at 15:37
  • @ChrisG I followed this tutorial [reactjs on youtube](https://www.youtube.com/watch?v=sBws8MSXN7A). Can you give me a possible idea about how to upload local csv file to the server? Thank you – beyond_inifinity Apr 08 '19 at 15:40
  • 1
    Uploading a file works like [this](https://stackoverflow.com/questions/36067767/how-do-i-upload-a-file-with-the-js-fetch-api). The fact that you're using React is irrelevant to the actual upload. React is not concerned with server communication. –  Apr 08 '19 at 15:52
  • @ChrisG the point is my back-end api-route to access google cloud and server.js are done. what I want to do is create several components to upload the file and post request to the server or check new records from google cloud. As new a bie, could you direct me correct way? Would you mind to provide sketch solution that I could follow up? I am bit lost honestly. Thank you – beyond_inifinity Apr 08 '19 at 15:58
  • You already have an entry point, namely your `pressButton` function. I also linked you to a question dealing with uploading a file via AJAX. Not sure what you're asking exactly? You have `this.state.file`, you have [how to upload](https://stackoverflow.com/a/36082038/5734311), what exactly are you missing? –  Apr 08 '19 at 18:13

2 Answers2

0

You are declaring a class inside a class, and you shouldn't use React.CreateClass anymore since its deprecated. Also, you have to import ReactDOM in order to use it (at the bottom of your file).

I don't know why you need the App component, but I editted your code to include the correct syntax (Can't really check the csv upload logic).

I'm assuming that you're using some sort of a request helper library. in this example I use axios.

I don't really know the FileReader api, but if I understand it correctly, onloadend returns the file data. After that we can send the data to the server (where we use axios.post).

The next step would be to define an endpoint on the server (I'm assuming express) that gets the data and saves it to the server using the fs module (HINT: fs.writeFile).

import ReactDOM from 'react-dom';
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import axios from 'axios';

class App extends Component {
  render() {
    return (
      <FormBox />
    )
  }
}

class FormBox extends Component {
    constructor(props) {
      super(props);
      this.state = {
        file: '',
        filePreviewUrl: ''
      }
    }

    uploadCSV(e) {
      e.preventDefault();
      let reader = new FileReader();
      let file = e.target.files[0];

      reader.onloadend = (error, data) => {
        if (error) throw new Error('Oops! something went wrong!');
        axios.post('http://your-link-goes-here/', {data: data}).then(data => {
          this.setState({
            file: file,
            filePreviewUrl: reader.result
          });
        })
      }
      reader.readAsDataURL(file);
    }
    render() {
      let {filePreviewUrl} = this.state;
      let filePreview = null;
      if (filePreviewUrl) {
        filePreview = (<img src={filePreviewUrl} />);
      } else {
        filePreview = (<div className="previewText">Please select an Json for Preview</div>);
      }
      return (
        <div>
        <form action='.' enctype="multipart/form-data">
          <input type='file'  onChange={this.uploadCSV}/>
          <button onClick={(e) => this.uploadCSV(e)}> Get it </button>
        </form>
        <div className="filePreview">
          {filePreview}
        </div>
        </div>
      )
    }
}
ReactDOM.render(<App />, document.getElementById('root'))
Sagi Rika
  • 2,839
  • 1
  • 12
  • 32
  • my code is a bit confusing. Basically, I want to build a component that uploads a file by sending a post request to the server. How could you make your code works for this purpose? Thanks – beyond_inifinity Apr 08 '19 at 16:05
  • Edited the code (now includes a request to your server) @beyond_inifinity – Sagi Rika Apr 08 '19 at 16:27
0

So you're mixing up some syntax for declaring React components. Here it is rewritten with a working codesandbox: https://5y03xnvpqx.codesandbox.io/

import React, { Component } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class FormBox extends Component {
  constructor(props) {
    super(props);
    this.state = {
      file: "",
      filePreviewUrl: ""
    };
    this.pressButton = this.pressButton.bind(this);
    this.uploadCSV = this.uploadCSV.bind(this);
  }

  pressButton(e) {
    e.preventDefault();
    console.log("handle uploading-", this.state.file);
  }

  uploadCSV(e) {
    e.preventDefault();
    let reader = new FileReader();
    let file = e.target.files[0];

    reader.onloadend = () => {
      this.setState({
        file: file,
        filePreviewUrl: reader.result
      });
    };
    reader.readAsDataURL(file);
  }

  render() {
    const { filePreviewUrl } = this.state;
    let FilePreview = null;
    if (filePreviewUrl) {
      FilePreview = <img src={FilePreviewUrl} />;
    } else {
      FilePreview = (
        <div className="previewText">Please select an Json for Preview</div>
      );
    }
    return (
      <div>
        <form action="." enctype="multipart/form-data">
          <input type="file" onChange={this.uploadCSV} />
          <button onClick={this.pressButton}> Get it </button>
        </form>
        <div className="filePreview">{FilePreview}</div>
      </div>
    );
  }
}

function App() {
  return (
    <div className="App">
      <FormBox />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

You'll notice that I put filePreviewUrl in lower case. By convention, React components are uppercase, so when you see something that's uppercase, you expect that it's eventually going to become a component. If that's not the case, best to leave it lowercase.

Justin Smith
  • 346
  • 1
  • 3
  • 17