Cuero
Cuero

Reputation: 1209

React-router 2.0 browserHistory doesn't work when refreshing

Below codes report 404 not found when refreshing on page http://localhost/about. But if browserHistory is changed to hashHistory, it works fine.

Here are my js file.

import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, IndexRoute, Link, IndexLink, browserHistory, hashHistory } from 'react-router';
import $ from 'jquery';

class App extends Component {
  render() {
    return (
      <div>
        <h1>APP!</h1>
        <Link to="/about">/about</Link>
        {this.props.children}
      </div>
    )
  }
}

class About extends React.Component {
  render() {
    return (
      <div>
        <h2>About 33</h2>
      </div>
    )
  }
}

var routes = (
    <Router history={hashHistory}>
        <Route path="/" component={App} />
        <Route path="/about" component={About} />
        <Route path="/wealth" component={WealthExpectation} />
    </Router>
)

$(document).ready(function() {ReactDOM.render(routes, document.getElementById("hello"))});

And the html file.

<!doctype html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Hello React</title>
        <script type="text/javascript" src="/static/js/jquery-1.12.2.min.js"></script>
        <script type="text/javascript" src="/static/js/script.js"></script>
        <!-- build:css -->
          <link rel="stylesheet" type="text/css" href="/static/bower_modules/c3/c3.min.css">
        <!-- endbuild -->
    </head>
    <body>
        <div id="hello">a</div>
        <div id="world"></div>
    </body>
</html>

I've read the questions on react-router v2.0 browserHistory not working and React-router urls don't work when refreshing or writting manually. For the first one, I've already set the path to absolute path, but still not working. For the second one, I tried to import express but failed ('Uncaught TypeError: Cannot read property 'prototype' of undefined').

Upvotes: 12

Views: 38952

Answers (6)

Sonu Bhatt
Sonu Bhatt

Reputation: 101

if you are using netlify to deploy your site you can create a file _redirects to you public directory and add a simple line in it

/*    /index.html   200

index.html is just a file which you are using in the public folder like this example

enter image description here

_redirect file

enter image description here

Upvotes: 3

Tom Tom
Tom Tom

Reputation: 3698

I've got URL workings by adding this line to the NGINX server block

try_files $uri $uri/ /index.html

Server gives you a 404 because the /about doesn't exit. You have to force every request thru the index file of your build so that the Router component can pick up on the /about and load the page properly.

Upvotes: 1

Ignacio Segura
Ignacio Segura

Reputation: 698

An alternative, simple and low-cost approach is to make Apache map any request to your React app. For example: http://localhost/about goes internally thru http://localhost/[my-own-html-file.html]

For example, if our React app starts at index.html, you need to create a .htaccess file on your React app and insert the following code:

# Map all non-existing URLs to be processed by index.html,
# so any URL that doesn't point to a JS file, CSS file, etc etc...
# goes through my React app.

<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^ index.html [L]
</IfModule>

BTW, this HTACCESS code was adapted from Drupal 8: https://github.com/drupal/drupal/blob/8.2.x/.htaccess

Upvotes: 14

jmancherje
jmancherje

Reputation: 6633

To expand on Phi Nguyen's answer the reason hashHistory works and browserHistory fails is because hashHistory is sort of a 'hack' or workaround to allow your app to manipulate the URL without the browser noticing and sending a GET request to your server. Essentially everything after the Hash is ignored.

browserHistory is generally preferred because it looks better but you no longer get the hash workaround and you need other means of preventing your browser from trying to send requests to your server. IF you are using webpack there is a simple way to essentially make all requests fallback to a single request. For example:

GET to http://localhost:8080/ AND a GET to http://localhost:8080/about would both fallback to http://localhost:8080/ and react-router would deal with the /about. (this is the reason you are able to navigate to /about fine, but if you refresh you get a 404 error, you're sending a GET to /about which doesn't exist on your server)

To do this you need to implement a webpack feature called history api fallback. There's two ways of doing that.

From the react-router docs / tutorial you can setup your start script to look like this:

"start": "webpack-dev-server --inline --content-base . --history-api-fallback"

Where the --history-api-fallback is the important piece for anyone with this error.

OR you can change your webpack.config.js file to look handle this on your dev server.

  devServer: {
    historyApiFallback: true,
    ...other stuff..
  },

Upvotes: 29

Phi Nguyen
Phi Nguyen

Reputation: 3056

When you use browser history, the server doesn't know how to handle the URL which is changed in the browser only. This tutorial will teach you how to remove # in url and make browser history work.

Upvotes: 2

Antonis Zisis
Antonis Zisis

Reputation: 2049

In order to use browserHistory you need to implement an express server to handle real URLs. hashHistory doesn't need an express server.

Have a look on the following guide:

https://github.com/reactjs/react-router/blob/master/docs/guides/Histories.md

Upvotes: 1

Related Questions