I am trying to use reactjs
and react-router
(1.x
) with my Django application but I am having a hard time putting all this together. Here is the github project just incase I dont provide enough information within this question.
https://github.com/liondancer/django-cherngloong
I created a path="about"
within my routes.js
var routes = (
<Router>
<Route path="/" component={ Views.Layout }>
<IndexRoute component={ Views.Index } />
<Route path="about" component={ Views.About } />
</Route>
<Route path="*" component={ Views.RouteNotFound } />
</Router>
);
export default routes;
My layout.js
class Layout extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div id="review-web">
<header className="header">
<LogoElement />
<CenterPiece />
</header>
<div>
{ React.cloneElement(this.props.children, { path: this.props.path }) }
</div>
<Footer />
</div>
);
}
}
export default Layout;
When I enter in localhost.8000/about
I get a 404
Django error
My goal is to keep the frontend and backend separate so I believe I should be able to use Django as just an endpoint for data and not for rendering views.
I faced with the same issue and ended up with this solution.
settings.py:
REACT_ROUTES = [
'login',
'signup',
'password-reset',
'password-change',
'about',
...
]
urls.py:
routes = getattr(settings, 'REACT_ROUTES', [])
urlpatterns = [
...
url(r'^(%s)?$' % '|'.join(routes), TemplateView.as_view(template_name='index.html')),
]
I don't like to duplicate all react-routes in django settings, but if we put everything there url(r'^.*$')
, server will always return HTTP status_code 200. And this is only one way to be able return valid HTTP status_code 404 for non existed urls.
My app serves the same client JS for all valid routes. Please excuse the Flask code.
@blueprint.route('/stuff/<path:path>', methods=["get"])
@blueprint.route('/', methods=["get"])
def index(path=None):
return render_template('app.html')
I could resolve this by using HashRouter
in the React app. This adds a #
to the beginning of the url and you can use an empty path in the Django urls.py
(your path would look like this: example.com/#/about/
)
Here is a good explanation (Don't forget to upvote).
Your files would look like this:
App.tsx
<Router>
<Switch>
<Route path="/article/:articleID">
<Article />
</Route>
{/* your routes */}
</Switch>
</Router>
And then simply an empty path. urls.py
urlpatterns = [
path("", TemplateView.as_view(template_name='index.html'))
]
I was inspired by ramusus' answer. I'm using the (I think) newer django.urls.re_path
. I'm a bit skeptic about this comment and if it would be better or worse if the 404 was handled by the frontend. This is how I implemented it:
from django.shortcuts import render
def index(request):
return render(request, 'frontend/index.html')
from django.urls import re_path
# Catch all pattern
urlpatterns = [
re_path('.*/', views.index, name='index'),
]
from django.contrib import admin
from django.urls import path, include
from rest_framework.authtoken import views
urlpatterns = [
path('admin/', admin.site.urls),
...,
path('api-auth/', include('rest_framework.urls')),
path('', include('some_apps.urls')),
...,
# Put this at the end! This way, Django tries all
# its API URLs and if it doesn't find anything it
# redirects to the frontend
path('', include('frontend.urls'))
]
// stuff ...
const Page404 = () => {
return (
<h3>404 - Not found</h3>
);
};
class App extends Component {
render(){
return (
<Router>
<Navbar />
<Switch>
// React handles any paths you specify, e.g. within the switch
<Route exact path='/some_paths/' component={SomeComponents} />
// If nothing matches...
<Route component={Page404} />
</Switch>
</Router>
)
}
}
// stuff...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With