Flask + React + SQLite

How do you pass a list of items stored in SQLite in Flask backe-end to React components? I can pass normal variables but not from the database…

you need to make an API endpoint which returns JSON:

https://riptutorial.com/flask/example/5831/return-a-json-response-from-flask-api

then in the front-end, use axios or fetch to retrieve the data and render the result in react

2 Likes

@stetim94 Thank you very much! I did create an API endpoint and used fetch method to retrieve data. However, now I face a different problem. Once I do that, my entire React ‘index.html’ simply looks blank. It is an entirely blank page, but I can see the correct output in developer tools… I don’t know what to do with it. If I stop displaying the output, the page looks normal. If I display the output - it looks blank. Can anyone help me with it? Any help would be appreciated!!!

No errors in the console to help you with?

Very difficult to say without seeing the code

@stetim94

My app is big, so I will send you the lines that were written to perform this task only.

  1. Creating an API endpoint in Flask:
db = SQLAlchemy(app)
ma = Marshmallow(app)

class RecipeModel(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    recipe_title = db.Column(db.String(50), index = True, unique = True)
    recipe_description = db.Column(db.String(300), index = True)
    recipe_image_relative_path = db.Column(db.String(1000), index = True, unique = True)
    recipe_ingredients = db.Column(db.String(1000), index = True, unique = False)
    recipe_date_created = db.Column(db.DateTime, default=datetime.utcnow)
    recipe_cousine = db.Column(db.String(30), index = True)

class RecipeSchema(ma.Schema):
    class Meta:
        fields = ('id','recipe_title','recipe_description','recipe_image_relative_path',
        'recipe_ingredients','recipe_date_created', 'recipe_cousine')

recipe_schema = RecipeSchema() # for console not to give us a warning
recipes_schema = RecipeSchema(many=True) # dealing with more than one product

@app.route('/api', methods = ['GET'])
def get_all_products():
    all_products = RecipeModel.query.all()
    result = recipes_schema.dump(all_products)
    return jsonify(result)
  1. Checking the output
    When I run Flask, the output at ‘http://127.0.0.1:5000/api’ looks like this:
[{"id":1,"recipe_cousine":"Russian","recipe_date_created":"2020-09-10T17:12:00.949621","recipe_description":"Very tasty - very Russian!!!!","recipe_image_relative_path":"101223020_1114703942235117_1531823300416634880_n.jpg","recipe_ingredients":"All for the BORSCH!!!","recipe_title":"Borsch"},{"id":2,"recipe_cousine":"Italian","recipe_date_created":"2020-09-12T09:18:55.495636","recipe_description":"Great Italian meal","recipe_image_relative_path":"lasagna_1.jpg","recipe_ingredients":"Meat, cheese","recipe_title":"Lazagna"}]
  1. Writing a fetch() function to retrieve data in React.
    Data-fetching component:
import React from 'react';
import App from '../../App'

class recipeData extends React.Component{

    constructor(props){
        super(props);
        this.state = {
            recipesJS: [],
            isLoaded: fasle
        }
    }

    componentDidMount(){
        fetch('http://127.0.0.1:5000/api').then(
            response => response.json()).then(
                json => {
                    this.setState({
                        recipesJS: json,
                        isLoaded: true
                    })
                }
            )
    }

    render(){
        return <App recipesJS={this.state.recipesJS} isLoaded={this.state.isLoaded}/>
    }

}

  1. Rendering information in App component.
import React from 'react';
import logo from './logo.svg';
import './App.css';


function App () {

    return (
      <div className="App">
        <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <p>
              Edit <code>src/App.js</code> and save to reload.
        </p>
            <p>{window.token}</p>
            <p>{window.image}</p>
            {this.props.recipesJS.map(r => (
              <p>{r.recipe_title}</p>
            ))}
            <a
              className="App-link"
              href="https://reactjs.org"
              target="_blank"
              rel="noopener noreferrer"
            >
              Learn React
        </a>
          </header>
        </div>
      );
}

export default App;
  1. Rendering React template in Flask.
@app.route('/react')
def react():
    return render_template('index.html', token = 'Greetings from Flask!', 
    image = 'rise and shine!')

Additional: I experimented with how to pass normal objects (not from a database) from Flask to React and this is how it works: I pass a variable in Flask render_template, then in React’s ‘index.html’ I put a script tag with window.[variable] to pass it to the actual React componenets. Here is my ‘index.html’:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
    <script>window.token = "{{ token }}", window.image = "{{ image }}", window.recipes = "{{ recipes }}" </script>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

@stetim94

Here is the update. I realized that I did not pass props to my stateless functional component. I passed it and instead of displaying a blank page, it actually does render the basic React page with my custom minor modifications. However, this time I get an error that .map() function is undefined. I have tried many different ways of displaying the database entities, but none of them worked.

Here is my latest version of App.js:

import React from 'react';
import logo from './logo.svg';
import './App.css';


function App (props) {

    return (
      <div className="App">
        <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <p>
              Edit <code>src/App.js</code> and save to reload.
        </p>
            <p>{window.token}</p>
            <p>{window.image}</p>
            <p>{props.recipesJS.map(r => (
              <span>{r.recipe_title}</span>
            ))}</p>
            <a
              className="App-link"
              href="https://reactjs.org"
              target="_blank"
              rel="noopener noreferrer"
            >
              Learn React
        </a>
          </header>
        </div>
      );
}

export default App;

could you provide me the full exact error message?

react-dom.production.min.js:209 TypeError: Cannot read property 'map' of undefined
    at s (App.js:17)
    at Ki (react-dom.production.min.js:153)
    at vo (react-dom.production.min.js:261)
    at cu (react-dom.production.min.js:246)
    at ou (react-dom.production.min.js:246)
    at Zo (react-dom.production.min.js:239)
    at qo (react-dom.production.min.js:230)
    at Du (react-dom.production.min.js:281)
    at react-dom.production.min.js:284
    at tu (react-dom.production.min.js:240)
Za @ react-dom.production.min.js:209
react-dom.production.min.js:256 Uncaught TypeError: Cannot read property 'map' of undefined
    at s (App.js:17)
    at Ki (react-dom.production.min.js:153)
    at vo (react-dom.production.min.js:261)
    at cu (react-dom.production.min.js:246)
    at ou (react-dom.production.min.js:246)
    at Zo (react-dom.production.min.js:239)
    at qo (react-dom.production.min.js:230)
    at Du (react-dom.production.min.js:281)
    at react-dom.production.min.js:284
    at tu (react-dom.production.min.js:240)

so recipeJS attribute does not exists on props, so doing props.recipesJS will give undefined. .map() only works on array

Is there a way to see for you/me what is inside props?

I think I have figured the problem out. Since I combine Flask and React, somehow App.js and ‘index.html’ get their way to the static folder in Flask. So, there is no any other React file, thus, there is no recipeJS…

@stetim94

Can you help me understand this error.

Objects are not valid as a React child (found: object with keys {id, recipe_cousine, recipe_date_created, recipe_description, recipe_image_relative_path, recipe_ingredients, recipe_title}). If you meant to render a collection of children, use an array instead.

I have figured another way to pass the props. It definitely got the prop, but struggles to render it.

I have solved it! Ihonestly do not know how, but I did! I will send the entire framework later tonight for future reference, shall anyone encounter a similar issue.

@stetim94 Thank you very much for your help! I would’ve given up on this without you)

best make a github repository and share that.

Not sure if you already do, but using git (version control) is a good idea when your project becomes larger. You can keep track of the changes you make