MERN Part II: Building the frontend of a RESTful API with React

nikki ricks
7 min readSep 8, 2020

This is part two of the tutorial I wrote Building RESTful APIs with Node.js and Express now we’re going to cover the frontend of our MERN with React and complete our app! Get. ex. cited.

  • M — MongoDB ✅
  • E — Express ✅
  • R — React ✅
  • N — Node.js ✅

Again this was inspired and heavily sourced from Emmanuel Henri but this time I referenced his MERN Essential Training on LinkedIn Learning.

Just want to emphasis that you will not be able to use this tutorial without building the backend first so start here!

What it will look like:

UI of the MERN app

Libraries and frameworks being used:

  • React — open-source JavaScript library for building user interfaces or UI components
  • CORS — node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options
  • Materialize — is a modern responsive CSS framework based on Material Design by Google.
  • Axios — Promise based HTTP client for the browser and node.js

VSCode Extension:

In your antiracism app first create a folder called backend:

antiracism_mern$ mkdir backend

and move (easiest to select all and drag) all of the previous content from the last post in the backend.

Now at the root of your app create the front end of your app, in the terminal run:

antiracism_mern$ npx create-react-app frontend

From your root folder you should have two folders:

Frontend and Backend folders MERN App

Now in your frontend terminal add CORS:

frontend$ npm i cors

For our CSS we’re going to be using Materialize so head over to the site and copy the CDN version:

<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">

<!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>

Go back into your app and in the index.html located in your frontend > public folder.

You want to copy the CSS stylesheet link ( code under <!-- Compiled and minified CSS -->)and paste it under the manifest links around line 18.

Then paste the JavaScript code (code under <!-- Compiled and minified JavaScript -->)before the body closing tag (</body>)around line 45.

Now you can start the react app in the terminal by running:

frontend$ npm start

Your browser should pop up on localhost:3000 and look like this:

Let’s set up the app structure and create a few folders. From your frontend folder:

frontend$ cd src

And now create a Components folder:

src$ mkdir Components

Then in the Components folder:

src$ cd Components

And now create a folder called Donation:

components$ mkdir Donation

Head into your Donation folder:

components$ cd Donation

And create 3 files:

Donation$ touch DonationForm.js DonationList.js

Now in VSCode in the folder panel, click on App.css and App.js and move them into the Components folder.

Head back into the src folder and make a folder called Tests:

src$ mkdir Tests

Highlight App.test.js and drag it into the Tests folder

Your folder structure should look like this:

folder structure MERN App

Head into your App.test.js file and because we changed the location you want to change the App import to:

import App from '../Components/App';

Head to your App.css and delete all of the contents. We don’t need those files since we’re using the magic of Materialize.

Head into your index.js and do the same to locate the App:

import App from '../Components/App';

And remove the styles import:

import './index.css'

And delete the file index.css.

Now we’ve made all the changes we need to get started on building the app! Yay!

Head on over to your DonationList.js file and type in “imr” + tab and the magic of that Simple React Snippets extension should do the rest for you and look like this:

import React from 'react';

Then type in “sfc” + tab and type in DonationList, return a div with some text to get:

import React from 'react';const DonationList = () => {  return ( <div>    Donation List  </div> );}export default DonationList;

Now in the DonationForm.js type “ccc” + tab, type in DonationForm, return a div with some text to get:

import React from 'react';class DonationForm extends React.Component {  constructor(props) {    super(props);    this.state = {  }  }  render() {
return ( <div>
DonationForm
</div> );
}
}
export default DonationForm;

React may complain to make sure on the second line you have “React.Component {“

Now go to App.js

Remove the logo (no need for it):

import logo from './logo.svg

And remove every bit of code between the first div starting at the <header> to leave you with this:

import React from 'react';import './App.css';function App() {  return (    <div className="App">    </div>  );}export default App;

Now import the two files you just created at the top:

import DonationList from './Donation/DonationList'
import DonationForm from './Donation/DonationForm'

Now we’re going to set up the template structure using Materialize formatting in the return div enter the following:

return (  <div className="container-fluid">    <div className="row">      <div className="col s10"><DonationList /></div>    </div>    <div className="row">      <div className="col s10"><DonationForm /></div>    </div>  </div>);

Your browser should look really simple at this point:

Browser view of components

Now we’ll work on creating the state for the entire app. Head to your terminal and we’ll install axios:

frontend$ npm i axios

Now in your App.js file we’ll do some refactoring, you’ll make it a class, add rendering and a constructor and passing props,assigning props, creating state and calling to our api that we built in our backend all before the return. This is what that looks like:

class App extends React.Component {  constructor(props) {    super(props)    this.state = {      donations: [],      currentDonation: {},    }    this.updateCurrentDonation =      this.updateCurrentDonation.bind(this)  }  componentDidMount() {    const url = 'http://localhost:4000/donations'    axios.get(url, { crossdomain: true })      .then((Response) => {      this.setState({        donations: Response.data      })    })      .catch((error) =>        console.log(error))  }  updateCurrentDonation(item) {    this.setState({      currentDonation: item,    })  }  render () {

Still in the App.js we will pass this off the updateCurrentDonation method to the DonationList component:

<div className="col s10"><DonationList donations={this.state.donations}updateCurrentDonation={this.updateCurrentDonation}/></div>

Now head into the DonationList.js file. And write some code to pass in the props, view the list of all the donations we’ve made and have a reduce method that shows the total of all of the donations at the bottom:

const DonationList = (props) => {  return (    <div>      <h4>Donations</h4>      <ul className="collection">      {props.donations.map((item) => (        <div className="collection-item" key={item._id}       onClick={props.updateCurrentDonation.bind(this,item)}>.    {item.organizationName} - ${item.dollarAmount}      <li>        {item.comment}      </li>      </div>      ))}    </ul>      <h5>Total: $ {props.donations.reduce((totalDonations, donation) => totalDonations + donation.dollarAmount, 0)}</h5>  </div> );}

Which depending on the data you have in your api it should look something like this:

Frontend view of donation list

Yay! Now let’s look at the form component. We’ll again be leveraging Materialize formatting to make this easy, creating a submitDonation function, adding an onSubmit to our form, labeling our input id’s, adding in axios to do a post to our backend API for all of our data, organization name, dollar amount and comment:

import React from 'react';
import axios from 'axios';
class DonationForm extends React.Component { submitDonation(event) { event.preventDefault() axios.post('http://localhost:4000/donations', { organizationName: this.refs.organizationName.value, dollarAmount: this.refs.dollarAmount.value, comment: this.refs.comment.value, }) .then((response) => { console.log(response) }) .catch((error) => { console.log(error) }) } render() { return ( <div className="row"> <h4 className="center">Add a new donation</h4> <form className="col s12" onSubmit={this.submitDonation.bind(this)}> <div className="row"> <div className="input-field col s6"> <input id="organizationName" ref="organizationName" type="text"/> <label htmlFor="organizationName">Organization Name</label> </div> <div className="input-field col s6"> <input id="dollarAmount" ref="dollarAmount" type="text"/> <label htmlFor="dollarAmount">Dollar Amount</label> </div> <div className="input-field col s6"> <input id="comment" ref="comment" type="text"/> <label htmlFor="comment">Comment</label> </div> </div> <button className="btn waves-effect waves-light" type="submit" name="action">Add donation</button> </form> </div> ); }}export default DonationForm;

Which should look like this in your browser and try it out it should now work!

Donation form

You may run into Cross-Origin Resource Sharing (CORS) issues like I did.

In your backend>index.js enter the following code right after your app.use bodyParser lines:

app.use(function(req, res, next) {res.header('Access-Control-Allow-Origin', '*');res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');next();});

If you want to extend the app to edit and delete you can do that too but I was happy with just creating donations at this point.

Final MERN stack app

There you have it! A full MERN stack app!

Hope you feel the same kind of excitement as I did when I made a MERN app for the first time! :) Congrats!

--

--