Python + Flask Pt 2 ... adding React
Published: 2021-08-16 02:02:43

The last post was about creating a Python + Flask application and deploying on Heroku.  This post we are going to take that same Python + Flask application and add a React frontend to it.  First some unfinished touches on the Python + Flask backend.  To make it run locally, we'll need to make some changes:

In our app.py, we are going to add CORS functionality and we are going to change our output from a simple string to a JSON object.  
```
from flask import Flask
from flask_cors import CORS #comment this on deployment

app = Flask(__name__)
CORS(app) #comment this on deployment

@app.route("/")
def hello_world():
    return {
      'resultStatus': 'SUCCESS',
      'message': "Hello, World!"
      }
```
We can now test the Flask server:
```
// ♥  flask run
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```
You may run into a lot of errors at this point.  You may need to adjust your Python installation or other modules.  When you get things finalized, what you see above will confirm that your Flask service is running.

When we view the output from the browser, we will see The JSON object output.  This is how we are going to display output from our backend through the React frontend.  It will look like this in the browser:
```
{
  "message": "Hello, World!",
  "resultStatus": "SUCCESS"
}
```
Now it's time to create the React front end.  You can create a separate repository or just a new subdirectory in the existing one.  That's all up to personal preference.  Once you decide what your "root" folder will be, you will use the "create react app" command from that directory:
```
npx create-react-app .
``` 
This will create a new React app in that root directory.  This could take some time and troubleshooting.  See the end message below.

Once the installation is successful, find 'app.js' in the 'src' subdirectory and make the following changes:
(some of this is referenced from the https://towardsdatascience.com/build-deploy-a-react-flask-app-47a89a5d17d9 tutorial)
```
import logo from './logo.svg';
import './App.css';
import React, { useEffect, useState } from 'react';
import axios from 'axios'

function App() {
  const [getMessage, setGetMessage] = useState({})
  useEffect(()=>{
    axios.get('http://localhost:5000').then(response => {
      console.log("SUCCESS", response)
      setGetMessage(response)
    }).catch(error => {
      console.log(error)
    })

  }, [])

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>React + Flask Tutorial</p>
        <div>{getMessage.status === 200 ? 
          <h3>{getMessage.data.message}</h3>
          :
          <h3>LOADING</h3>}</div>
      </header>
    </div>
  );
}

export default App;
```
The "stock" app.js file will already have some of this.  What we are going to add is:
```
import React, { useEffect, useState } from 'react';
import axios from 'axios'

```
"useEffect and useState" are called "React Hooks" and you can Google to read about them.  They essentially add functionality that allow you to use "state" and other React features without writing a class. "axios" is a component for React that allows "in render" async requests.  It can request information from and send information to other electronic sources and turn their output into React usable objects.  In this case we will get our "Hello, World" output from our backend server.
```
  const [getMessage, setGetMessage] = useState({})
  useEffect(()=>{
    axios.get('http://localhost:5000').then(response => {
      console.log("SUCCESS", response)
      setGetMessage(response)
    }).catch(error => {
      console.log(error)
    })

  }, [])

```
"useState" is going to create for us a pair of "setter / getter" functions.  "getMessage" will call to and collect the response from the axios request (axios.get) and "setGetMessage" will return the response.
```
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>React + Flask Tutorial</p>
        <div>{getMessage.status === 200 ? 
          <h3>{getMessage.data.message}</h3>
          :
          <h3>LOADING</h3>}</div>
      </header>
    </div>
  );
}
```
Next you will start the React server (yes, even though React is a "frontend framework" it runs in a separate server.)
```
npm start
```

The React app "return" renders the output based on the response from the backend server.  There is a conditional (ternary) view:
```
        <div>{
          getMessage.status === 200 
          ? 
          <h3>{getMessage.data.message}</h3>
          :
          <h3>LOADING</h3>
          }
       </div>

```
where until the response returns a status code of 200, the React component will only show the word "LOADING".  
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pjpee9chjakz6g9yl4ui.png)
Once the response returns the 200 status code, then the React component will re-render the "getMessage.data.message" that is returned from the "getMessage" function.  Since the response object has a "key" of "message":
```
{
  "message": "Hello, World!",
  "resultStatus": "SUCCESS"
}
```
the "value" of "message" is what is displayed, in this case "Hello, World!".
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0gnxra3l3m29jr1oa4ki.png)

"npm" is a Node package manager and installs are rarely without bumps so be ready to troubleshoot any "missing component" errors or other deprecation warnings.  Google is your friend and Node is very complicated.  You will end up with a "node_modules" folder that has anywhere from 20,000 to 30,000 resources that Node uses to make React work.  When you get installation errors, sometimes just repeating the command you just sent - that gave you those errors - is all you need to do.  Other times, it's more complicated.  Read the errors closely and try to find competent resources for steps to take for corrections.  Good luck!