How ReactJS And Node Back-end Server API Are Helpful While Developing An App

Before we combine these technologies, let us understand them on a separate basis.

React JS

React JS is a JavaScript library mainly used for the development of front-end user interfaces. Maintained by Facebook, along with a wide range of individual developers and companies. One of the main reasons why React is highly used is to fetch rapidly changing data which also needs to be recorded. Still, confused about what exactly React is? Well, it is one of the most popular JavaScript libraries and not a framework of any sort. Secondly, being an open-source project,  React is mainly used to build user interfaces (UI) on the front-end. Lastly, React js developers are able to create components that are mainly custom HTML elements that are reusable for a quick and efficient build-up for user interfaces.   

React can also streamline how data is stored and handled, making the best use of state and props. 

Pros

  1. Easy to learn and use 
  2. Easier dynamic development of web
  3. Components can be reused when using react
  4. Brings enhancement in performance 
  5. SEO friendly unlike that of any JavaScript frameworks

Cons

  1. Rapidly changing environment makes it difficult for developers
  2. Lack of proper documentation
  3. Only takes the view part of the application development

Node.JS

Being a JavaScript runtime environment, Node.JS can be used as a complete package that incorporates everything that is required to execute a program in JavaScript. This is now possible only because when Node js developers tried to extend their functionalities from something that could only run on the browser to one that could be run standalone on a machine. NodeJS is presently used to run server-side scripts and brings together web application development around one programming language.  

Getting Started

Let’s start with the backend first! Try to write a server application featuring all the necessary configurations required to accept cross-origin requests and uploading files. Install user-generator which turns out to be the official and quickest way to start with an Express back-end application. 

npm install -g express-generator

As soon as a React JS developer installs this module globally from the terminal. After installing this global npm module, we have an instance of it named express to generate our project structure. 

mkdir fileupload-example
express server
cd server

When changing the current directory to the project express command just scaffolded, we can observe the following structure and files:

Try running this backend server on default configuration, we have to install the dependencies mentioned in package.json first

npm install
npm start

Express-generator comes with the following dependencies:

"dependencies": {
    "body-parser": "~1.18.2",
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.9",
    "express": "~4.15.5",
    "jade": "~1.11.0",
    "morgan": "~1.9.0",
    "serve-favicon": "~2.4.5"
}

Moreover, you can add two more packages for our configurable back-end application to behave in the way we want to. 

npm install --save cors express-fileupload

By doing this, you are providing a middleware function for express applications to enable various Cross-origin Resource Sharing Options. CORS is a mechanism that allows restricted resources (in our case, API, or AJAX requests) on a web page from another domain. It helps a browser and a server to communicate and can be hosted on separate domains. You will understand it more when you will see it in action.

The other module, express-file upload is a bare minimum express middleware function for uploading files. The advantage of it is that it supports for Promises and can handle multiple file uploads. Now you can start by modifying the default Express back-end in the file. 

const express = require('express');
const path = require('path');
const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const cors = require('cors'); // addition we make
const fileUpload = require('express-fileupload'); //addition we make
const index = require('./routes/index');
const users = require('./routes/users');
const app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());

// Use CORS and File Upload modules here
app.use(cors());
app.use(fileUpload());
app.use('/public', express.static(__dirname + '/public'));
app.use('/', index);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  const err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

At the same time, you need to allow data coming from a foam. For this, we have to enable urlencoded options of the body-parser module and specify a path in order to store the image file coming from the client.

With this, we can see if our server is working correctly by running:

npm start

If you get the screen below by navigation on port http://localhost:3000, it means that our server is running perfectly.

Connecting ReactJS Frontend with NodeJs Backend

Setting up the front-end

Here I would like to mention another command-line utility used to create a default Reactjs front-end application.

create-react-app node-react-fileupload-front-end

Next is the File upload form where we provide access to the value that is a file using refs. Ref is a special attribute that can be attached to any component in React. It takes a callback function and this callback will be executed immediately after the component is mounted. It can be also be used on an HTML element and the callback function associated will receive the DOM element as the argument. This way, the ref can be used to store a reference for that DOM element. That is exactly what we are going to do.

class App extends Component {
// We will add this part later
  render() {
    return (
      <div className="App">
        <h1>FileUpload</h1>
        <form onSubmit={this.handleUploadImage}>
          <div>
            <input
              ref={ref => {
                this.uploadInput = ref;
              }}
              type="file"
            />
          </div>
          <br/>
          <div>
            <input
              ref={ref => {
                this.fileName = ref;
              }}
              type="text"
              placeholder="Enter the desired name of file"
            />
          </div>
          <br/>
          <div>
            <button>Upload</button>
          </div>
          <hr/>
          <p>Uploaded Image:</p>
          <img src={this.state.imageURL} alt="img"/>
        </form>
      </div>
    );
  }
}

The input element must have the type=”file” otherwise it would not be able to recognize what type we are using it for. It is similar to the values like email, password, etc.The handleUploadImage method will take care of the API calls that we need to request to the server. If that call is successful, then the local state of our React application will be set to let the user know that the upload was successful. Inside this function, to make the API call, we will be using the axios library that we installed when setting up our front end app.

constructor(props)
{
  super(props);
  
  this.state = {
    imageURL: ''
  };
  
  this.handleUploadImage = this.handleUploadImage.bind(this);
}

handleUploadImage(ev)
{
  ev.preventDefault();
  
  const data = new FormData();
  data.append('file', this.uploadInput.files[0]);
  data.append('filename', this.fileName.value);
  
  fetch('http://localhost:4000/upload', {
    method: 'POST',
    body: data
  }).then(response => {
    response.json().then(body => {
      this.setState({imageURL: `http://localhost:4000/${body.file}`});
    });
  });
}

Updating the server to handle AJAX Request

app.post('/upload', (req, res, next) => {
// console.log(req);
  let imageFile = req.files.file;
  imageFile.mv(`${__dirname}/public/${req.body.filename}.jpg`, err => {
    if (err) {
      return res.status(500).send(err);
    }
    res.json({file: `public/${req.body.filename}.jpg`});
    console.log(res.json);
  });
});
npm start

If everything falls into place,  successfully called and everything is working fine. Once the file is uploaded to the server, it will be sent back to the client to reflect that the user has successfully uploaded the file.

1 Comment

  1. Hey i am one of your oldest YouTube subscriber. I love the way you explain each and every little detail. You helped me allot learning laravel in level for beginners playlist.

Leave a Reply