React-router urls don't work when refreshing o

2018-12-31 02:49发布

I'm using React-router and it works fine while I'm clicking into link buttons, but when I refresh my webpage it does not load what I want.

For instance, I am into localhost/joblist and everything is fine because I arrived here pressing a link. But If I refresh the webpage I get: Cannot GET /joblist

By default It didn't work like this. Initially I had my URL: localhost/#/ and localhost/#/joblist and they worked perfectly fine. But I don't like this kind of url, so trying to erase that '#' I wrote:

Router.run(routes, Router.HistoryLocation, function (Handler) {
 React.render(<Handler/>, document.body);
});

This problem does not happen with localhost/, this one always returns what I want.

EDIT: This app is single-page, so /joblist don't need to ask anything to any server.

EDIT2: My entire router.

var routes = (
    <Route name="app" path="/" handler={App}>
        <Route name="joblist" path="/joblist" handler={JobList}/>
        <DefaultRoute handler={Dashboard}/>
        <NotFoundRoute handler={NotFound}/>
    </Route>
);

Router.run(routes, Router.HistoryLocation, function (Handler) {
  React.render(<Handler/>, document.body);
});

28条回答
不流泪的眼
2楼-- · 2018-12-31 02:59

If you are using Express or some other framework in the backend , you can add the similar configuration as below and check out the Webpack public path in the configuration, it should work fine even on reload if you are using BrowserRouter

` expressApp.get('/*', (request, response) => {
    response.sendFile(path.join(__dirname, '../public/index.html'));
  });`
查看更多
浅入江南
3楼-- · 2018-12-31 02:59

I had this same problem and this solution worked for us..

Background:

We are hosting multiple apps on the same server. When we would refresh the server would not understand where to look for our index in the dist folder for that particular app. The above link will take you to what worked for us... Hope this helps, as we have spent quite a hours on figuring out a solution for our needs.

We are using:

package.json

"dependencies": {
"babel-polyfill": "^6.23.0",
"ejs": "^2.5.6",
"express": "^4.15.2",
"prop-types": "^15.5.6",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-redux": "^5.0.4",
"react-router": "^3.0.2",
"react-router-redux": "^4.0.8",
"redux": "^3.6.0",
"redux-persist": "^4.6.0",
"redux-thunk": "^2.2.0",
"webpack": "^2.4.1"
}

my webpack.config.js

webpack.config.js

/* eslint-disable */
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const babelPolyfill = require('babel-polyfill');
const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
  template: __dirname + '/app/views/index.html',
  filename: 'index.html',
  inject: 'body'
});

module.exports = {
  entry: [
    'babel-polyfill', './app/index.js'
  ],
  output: {
    path: __dirname + '/dist/your_app_name_here',
    filename: 'index_bundle.js'
  },
  module: {
    rules: [{
      test: /\.js$/,
      loader: 'babel-loader',
      query : {
          presets : ["env", "react", "stage-1"]
      },
      exclude: /node_modules/
    }]
  },
  plugins: [HTMLWebpackPluginConfig]
}

my index.js

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import Routes from './Routes'
import { Provider } from 'react-redux'
import { createHistory } from 'history'
import { useRouterHistory } from 'react-router'
import configureStore from './store/configureStore'
import { syncHistoryWithStore } from 'react-router-redux'
import { persistStore } from 'redux-persist'

const store = configureStore();

const browserHistory = useRouterHistory(createHistory) ({
  basename: '/your_app_name_here'
})
const history = syncHistoryWithStore(browserHistory, store)

persistStore(store, {blacklist: ['routing']}, () => {
  console.log('rehydration complete')
})
// persistStore(store).purge()


ReactDOM.render(
    <Provider store={store}>
      <div>
        <Routes history={history} />
      </div>
    </Provider>,
  document.getElementById('mount')
)

my app.js

var express = require('express');
var app = express();

app.use(express.static(__dirname + '/dist'));
// app.use(express.static(__dirname + '/app/assets'));
app.set('views', __dirname + '/dist/your_app_name_here');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');

app.get('/*', function (req, res) {
    res.render('index');
});

app.listen(8081, function () {
  console.log('MD listening on port 8081!');
});
查看更多
琉璃瓶的回忆
4楼-- · 2018-12-31 02:59

Its pretty simple when you got cannot get 403 error after refresh dom component. just add this one line in your web pack config, 'historyApiFallback: true '. this savez my whole day.

查看更多
千与千寻千般痛.
5楼-- · 2018-12-31 03:02

This can solve your problem

I also faced the same problem in ReactJS application in Production mode. Here is the 2 solution to the problem.

1.Change the routing history to "hashHistory" instead of browserHistory in the place of

 <Router history={hashHistory} >
   <Route path="/home" component={Home} />
   <Route path="/aboutus" component={AboutUs} />
 </Router>

Now build the app using the command

sudo npm run build

Then place the build folder in your var/www/ folder, Now the application is working fine with addition of # tag in each and every url. like

localhost/#/home localhost/#/aboutus

Solution 2 : Without # tag using browserHistory,

Set your history = {browserHistory} in your Router,Now build it using sudo npm run build.

You need to create the "conf" file to solve the 404 not found page, the conf file should be like this.

open your terminal type the below commands

cd /etc/apache2/sites-available ls nano sample.conf Add the below content in it.

 <VirtualHost *:80>
    ServerAdmin admin@0.0.0.0
    ServerName 0.0.0.0
    ServerAlias 0.0.0.0
    DocumentRoot /var/www/html/

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    <Directory "/var/www/html/">
            Options Indexes FollowSymLinks
            AllowOverride all
            Require all granted
    </Directory>
</VirtualHost>

Now you need to enable the sample.conf file by using the following command

cd /etc/apache2/sites-available
sudo a2ensite sample.conf

then it will ask you to reload the apache server,using sudo service apache2 reload or restart

then open your localhost/build folder and add the .htaccess file with content of below.

   RewriteEngine On
   RewriteBase /
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteCond %{REQUEST_FILENAME} !-l
   RewriteRule ^.*$ / [L,QSA]

Now the app is working normally.

Note: change 0.0.0.0 ip to your local ip address.

If any doubts regarding this feel free to raise a comment.

I hope it is helpful to others.

查看更多
千与千寻千般痛.
6楼-- · 2018-12-31 03:03

The answers here are all extremely helpful, what worked for me was configuring my Webpack server to expect the routes.

  devServer: {
    historyApiFallback: true,
    contentBase: './',
    hot: true
  },

The historyApiFallback is what fixed this issue for me. Now routing works correctly and I can refresh the page or type in the URL directly. No need to worry about work arounds on your node server. This answer obviously only works if you're using webpack.

EDIT: see my answer here for a more detailed reason why this is necessary: https://stackoverflow.com/a/37622953/5217568

查看更多
看淡一切
7楼-- · 2018-12-31 03:03

I used create-react-app to make a website just now and had the same issue presented here. I use BrowserRouting from the react-router-dom package. I am running on a Nginx server and what solved it for me was adding the following to /etc/nginx/yourconfig.conf

location / {
  if (!-e $request_filename){
    rewrite ^(.*)$ /index.html break;
  }
}

Which corresponds to adding the following to the .htaccess in case you are running Appache

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

This also seems to be the solution suggested by Facebook themselves and can be found here

查看更多
登录 后发表回答