2

Ours react app works in dev mode (localhost) perfectly, but when we put it onto the Heroku server we cannot access routes directly. When we do history.push({ }) to our path we get a 404 page.

You can see the page here: placemate.herokuapp.com

Steps to reproduce: go to the above URL, see it load. Then add /login to the URL bar and you will see that a 404 page appears. However, clicking a login from the header will direct you properly.

Here is our router code:

import React from 'react'
import { Switch, Route, Redirect } from 'react-router-dom'
import '../../App.css'
import Home from '../../scenes/general/home/Home'
import Login from '../../scenes/general/login/Login'
import Register from '../../scenes/general/register/Register'
import GuestHeader from '../../components/general/header/Header'

const Main = () => (
  <main className='main_app'>
      <GuestHeader />
      <Switch>
          <Route exact path='/' component={Home}/>
          <Route path='/login' component={Login}/>
          <Route path='/register' component={Register}/>
      </Switch>
    </main>
);

export default Main;

index.js file:

ReactDOM.render(<BrowserRouter><App /></BrowserRouter>, document.getElementById('root'));
registerServiceWorker();
8
  • 1
    There are two types of routing, one is handled by your react app, another is handled by your server. In your case, the later on is not working. You need to make sure, that if you hit '/login' in browser, it is getting served by react, not server. Commented Jan 28, 2018 at 15:25
  • To read more about the same, please follow the link: stackoverflow.com/questions/27928372/… Commented Jan 28, 2018 at 15:28
  • Thanks @learner i've been there but cant get any of the proposed solutions to work for me i'm afraid Commented Jan 28, 2018 at 15:32
  • Please describe your backend code a little bit. Commented Jan 28, 2018 at 15:34
  • I'm currently using standard reactjs webpack configuration, react-route-dom, what specifically do you mean by the backend code? I also updated my question to include the index.js code Commented Jan 28, 2018 at 15:37

1 Answer 1

6

Why 404 Not Found

This is because when you put up any path in your address bar its request is sent to the web server not react. As you know the react-router we are using is responsible to display the correct component based on the route, but since you pass the route to nginx / apache server not react-router; hence your web server tries to find www.example.com/login which actually does not exist. Hence you get 404 not found.

Solution

Try to create a .htaccess file on your web server public HTML root directory. Create some rules so that the request is always forwarded from the root path. This will let the react come into the picture, hence the react-router can grab the path and render the appropriate component.

For example, you can create something like this

For Apache server

RewriteEngine On        
  # If an existing asset or directory is requested go to it as it is
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
  #RewriteCond %{SERVER_PORT} 80 
  #RewriteRule ^(.*)$ https://www.example.com/$1 [R,L]
  RewriteRule ^ - [L]
  
  # If the requested resource doesn't exist the serve index.html
  RewriteRule ^ ./index.html

For Node.js

Sample code for node.js express server can be like this (present in file for server implementation, conventionally named as server.js)

const express = require('express');
const path = require('path');

const app = express();

if(process.env.NODE_ENV!== 'production'){
   //do something if you are in development environment

   //below lines only if you are using webpack based deployment

   const webpackMiddleware = require('webpack-dev-middleware');
   const webpack = require('webpack');
   const webpackConfig = require('./webpack.config.js');
   app.use(webpackMiddleware(webpack(webpackConfig)));
}
else{
  // in production env do following thing 
  app.use(express.static('public_html_folder'));//give user access to public assets

  //redirect all request to index.html for compatibality with react router
  app.get('*',(req,res)=>{
    res.sendFile(path.join(__dirname,'public_html_folder/index.html'));
  });
}

app.listen(process.env.PORT || 3050, () => console.log('Listening'));

I hope this solves your problem or at least give you an idea of what to do if there is a different backend server.

Sign up to request clarification or add additional context in comments.

1 Comment

The Apache server solution works for me. Thank you very much! This answer is very relevant +1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.