Flask and React routing
Solution 1
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.
Solution 2
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')
Solution 3
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')
knowbody
Hacker, software engineer. Addicted to coke, volleyball and programming. React fan. GitHub Twitter
Updated on August 18, 2022Comments
-
knowbody almost 2 years
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 getNot 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. -
shangsunset over 8 yearsif all the routes will be directed to catch all function, how would you separate backend api routes and react routes when i do a ajax request call from front end?
-
Dan Abramov over 8 years@shangyeshen Register API routes before catch-all so they have precedence.
-
juanitogan about 8 yearsIs there a complete example of this somewhere? The code here doesn't do any index rendering like the example above and I have been unable to combine the two in a way that works.
-
juanitogan about 8 yearsFound it. I couldn't get
@app.route('/<path:path>')
to match on anything until I figured out the poorly documented Flask parameters. Settingstatic_url_path=""
is bad. I ended up withstatic_url_path="/public", static_folder="../public"
. Then I return a static:return app.send_static_file("index.html")
with hard-coded"/public/..."
urls. Also, look at: reddit.com/r/reactjs/comments/42pn95/reactrouter_and_flask_404 (not me). -
Jason over 4 yearsThis is the solution I used for a while until I needed to break my bundle into parts using
React.lazy
.React.lazy
wants to get the bundle parts from thepath
instead of the static directory that flask is using. Any ideas on that? -
logeekal about 4 yearsHello @Jason, what is the issues your are getting in React.lazy. We are trying to go down this route and I am researching all pros and cons this approach. Thank you.
-
TheDiveO over 3 yearsCan't you replace the empty os.path.join(path_dir) with just a plain path_dir?
-
Sundios about 3 yearsThis works great! thanks for sharing this!