Flask and React routing

Question:

I’m building the Flask app with React, I ended up having a problem with routing.

The backend is responsible to be an API, hence some routes look like:

@app.route('/api/v1/do-something/', methods=["GET"])
def do_something():
    return something()

and the main route which leads to the React:

@app.route('/')
def index():
    return render_template('index.html')

I’m using react-router in the React app, everything works fine, react-router takes me to /something and I get the rendered view, but when I refresh the page on /something then Flask app takes care of this call and I get Not Found error.

What is the best solution? I was thinking about redirecting all calls which are not calling /api/v1/... to / it’s not ideal as I will get back the home page of my app, not rendered React view.

Asked By: knowbody

||

Answers:

We used catch-all URLs for this.

from flask import Flask
app = Flask(__name__)

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):
    return 'You want path: %s' % path

if __name__ == '__main__':
    app.run()

You can also go an extra mile and reuse the Flask routing system to match path to the same routes as client so you can embed the data client will need as JSON inside the HTML response.

Answered By: Dan Abramov

Maybe as extension to the answers before. This solved the problem for me:

from flask import send_from_directory

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def serve(path):
     path_dir = os.path.abspath("../build") #path react build
     if path != "" and os.path.exists(os.path.join(path_dir, path)):
         return send_from_directory(os.path.join(path_dir), path)
     else:
         return send_from_directory(os.path.join(path_dir),'index.html')
Answered By: Henrik

For some reason, the catch-all URLs did not work for me. I found that using the flask 404 handler results in the exact same thing. It sees the url and passes it down to react where your router will handle it.

@app.errorhandler(404)   
def not_found(e):   
  return app.send_static_file('index.html')
Answered By: João Ramiro

Just to inform handle error 404 and render_template works perfectly for me.

@app.errorhandler(404)
def not_found(e):
    return render_template("index.html")
Answered By: Kam Dane

I have to combine both catch-all and 404 handler for it to work properly. I am hosting a react-app in a subpath with its own redirection handler from react-router.

@app.route('/sub-path',  defaults={'path': 'index.html'})
@app.route('/sub-path/<path:path>')
def index(path):
    return send_from_directory('../react-dir/build', path)

@app.errorhandler(404)
def not_found(e):
  return send_from_directory('../react-dir/build','index.html')
Answered By: Dat Huynh
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.