FReMP Stack (Flask, ReactJS, MongoDB, Python)
Tags: flask, react, mongodb, python
Published: 2020-07-01 09:49:30

Technology keeps on evolving everyday and developers constantly look for more and more things to get their hands-on. In this article, I will be introducing a new full stack framework, called **FReMP**. The abbreviation used is not the best one, but it just gets the work done in justifiable ways.

- [What is FReMP?](#what-is-fremp)
* [How to install FReMP?](#how-to-install-fremp)
* [Building a simple app](#building-a-simple-app)

## What is FReMP?
**FReMP** stands for **F**lask, **Re**actJS, **M**ongoDB and **P**ython. Unlike **MEAN** and **MERN**, the FReMP stack uses Python to deal with the back end part. Therefore, all core operations such as creating and handling APIs or dealing with functional/OO logic can easily be dealt in Python. As for the front end, it uses Javascript, which allows you to do common operations, such as validating input fields and updating components on the DOM.

## How to install FReMP?
In this section, we will go through the steps to install the FReMP stack on a Linux environment(Ubuntu).

### 1. Install Flask

To install flask, we need to make sure Python is installed. Since Python is deprecated and Python3 has taken over, we will use Python3 for this tutorial. 

```
$ apt-get install python3
$ apt-get install python3-pip
$ sudo -H pip3 install flask
$ flask --version
```
  * **pip** is a package manager for python, and is used to install Flask globally on your environment using -H flag.
  * At the time of this writing, the latest version of Flask is 1.1.1

### 2. Install ReactJS

To install ReactJS, we need to install NodeJS first, then use npm/yarn to install the necessary modules. For this tutorial, we use install and use yarn.

```
$ apt-get install nodejs
$ sudo npm install -g yarn
$ sudo npm install -g npx
$ yarn --version
$ npx --version
```
  * **yarn** is a package manager for javascript and is much faster and lighter than npm.
  * **npx** is used to run the module create-react-app and this will create the starter project for our front end.

### 3. Install MongoDB

```
$ apt-get install mongodb
$ mongo --version
```

To ensure you have everything installed properly, check the version of each framework. If the versions show up without any error, you should be good to go.

## Building a simple app
In this section, we will build a simple interface that will, locally, allow the user to write his name in a form and on submitting the form, the name is saved in mongodb and at the same time all the names are retrieved and displayed on the user interface. Below is an example of how the final product will look like:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/yat7tto64alscu3x6usw.gif)

I did not focus on stylings so much, I tend to make it as minimal as possible for simplicity. So let's get started!

#### 1. Project Folder
We will start by making a root folder to contain both the front end and the back end of the application. In this case, we'll call the root folder 'frmp-app'. Feel free to call it whatever you want.

```
$ mkdir frmp-app
$ cd frmp-app
```

#### 2. Create React frontend folder
Secondly we'll create the front end folder and call it 'frontend'. To do so, run the following command and wait for it to finish:

```
$ create-react-app frontend
```
At this point, your directory should look like this:

```
~/frmp-app$ ls -al
total 16
drwxrwxr-x  4 akhil akhil 4096 zin 30 17:55 .
drwxr-xr-x 13 akhil akhil 4096 zin 30 17:39 ..
drwxrwxr-x  6 akhil akhil 4096 zin 30 17:44 frontend
```

After the folder 'frontend' is created, you can 'cd frontend' and start doing changes on the frontend foler. The first change you got to make is to define a proxy in _package.json_ file. 

```
  "proxy": "http://localhost:5000"
```
Add the line to the bottom of package.json. Whenever a request hits goes from localhost:3000, it hits the proxy and is redirected to localhost:5000. The backend processes the request with the information in it and replies back. After setting the proxy, we can implement the HTML form in the App.js component.

_src/App.js_
```javascript
import React, { Component } from 'react';
import './App.css';
import Results from './components/Results';
import NewName from './components/NewName';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: '',
      names: [],
      loading: true
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({ name: event.target.value });
  }

  async handleSubmit(event) {
    event.preventDefault();
    this.setState({
      loading: true,
    })
    await fetch('/addname/' + this.state.name, {
      method: 'GET'
    });
    this.getNames()
  }


  getNames() {
    fetch('/getnames/')
      .then(response => response.json())
      .then(json => {
        this.setState({
          name: '',
          names: json,
          loading: false
        })
      })
  }

  componentDidMount() {
    this.getNames();
  }

  render() {
    return (
      <div className="App">
        <header className="App-header">
          <NewName handleChange={this.handleChange} handleSubmit={this.handleSubmit} value={this.state.name} />
          {this.state.loading ? <h1>Loading</h1> : <Results {...this.state} />}
        </header>
      </div>
    );
  }
}

export default App;

```
As you may have seen, we have two components namely 'NewName' and 'Results'.

NewName is the component which contains the input bar. The user writes his name and press Enter.

_src/components/NewName.js_
```javascript
import React, { Component } from 'react';

class NewName extends Component {
    render() {
        return (
            <div>
                <form onSubmit={this.props.handleSubmit}>
                    <input
                        type="text"
                        name="newName"
                        value={this.props.value}
                        onChange={this.props.handleChange}
                        placeholder="New Name"
                        autoFocus
                        autoComplete='off'
                    />
                    <button type="submit">Add</button>
                </form>
            </div>
        )
    }
}

export default NewName;
```

Results is the component that displays the list of names.

_src/components/Results.js_
```javascript
import React, { Component } from 'react';

class Results extends Component {
    render() {
        return (
            this.props.names.map(row => 
                <div key={row.id}>
                    {row.name}
                </div>
            )
        )
    }
}

export default Results;
```

Now that we are completely done with the frontend section, we can change directory and move to the root directory and create our backend folder.

```
$ cd ..
```

#### 3. Create Flask backend folder
After creating our front-end starter project, we will set up our backend by creating a folder called 'backend' and keep all logic and operations related to APIs and database in here. To do so, run the following command:

```
$ mkdir backend
$ touch app.py
```

At this point, your directory should look like this:
```
~/frmp-app$ ls -al
total 16
drwxrwxr-x  4 akhil akhil 4096 zin 30 17:55 .
drwxr-xr-x 13 akhil akhil 4096 zin 30 17:39 ..
drwxrwxr-x  2 akhil akhil 4096 zin 30 18:01 backend
drwxrwxr-x  6 akhil akhil 4096 zin 30 17:44 frontend


```


_app.py_

```python
from flask import Flask, redirect, url_for
from pymongo import MongoClient
from flask_cors import CORS, cross_origin
import json

app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'


mongoClient = MongoClient('mongodb://127.0.0.1:27017')
db = mongoClient.get_database('names_db')
names_col = db.get_collection('names_col')

@app.route('/addname/<name>/')
def addname(name):
    names_col.insert_one({"name": name.lower()})
    return redirect(url_for('getnames'))

@app.route('/getnames/')
def getnames():
    names_json = []
    if names_col.find({}):
        for name in names_col.find({}).sort("name"):
            names_json.append({"name": name['name'], "id": str(name['_id'])})
    return json.dumps(names_json)

if __name__ == "__main__":
    app.run(debug=True)

```
Since we are connection Python with MongoDB, we will use pymongo and use the MongoClient function to establish the connection. MongoClient accepts a string as parameter, and the string is the url with the port that connects your pc to mongodb, i.e, _mongodb://127.0.0.1:27017_. In the cluster, we will create a database called _names-db_ and inside the database, we will create a collection, _names-col_, which will contain a list of json objects. Each object will the name input by the user. After getting the collection name, we define two methods, namely, addname and getnames. When _addname_ is called, it saves the name passed into the db. Then the second method calls all the names in the db and sends them to the frontend, on the component _Results_. 

#### 4. Mongo shell
This part is optional. If you want to see the names directly in your database, you can fire up the terminal and run mongo, which will open the mongo shell.
```
$ mongo
$ use names-db
$ db.names-col.find()
```

#### 5. Run the project
To run the project and see you app in action, you will open two terminals. On one terminal, change directory to frontend and on the other terminal, change directory to backend:

Inside your frontend directory, run
```
$ yarn start
```

Inside your backend directory, run
```
$ python3 app.py
```

If you followed the instruction clearly so far, this should run flawlessly.

Open up localhost:3000 on your browser to get the application live. 

Cheers!