【问题标题】:React routing not working while manually changing URL | React-router 4手动更改 URL 时反应路由不起作用 |反应路由器 4
【发布时间】:2017-05-25 10:50:26
【问题描述】:

当通过 React-router 的 Link 组件更改 URL 时,我的路由工作正常。但是,如果我尝试在浏览器中手动更改 URL,则会出现 404 错误。

下面是 routes.js 文件

import React from "react";
import {Route, Switch, NotFoundRoute} from 'react-router-dom';
import App from "./components/app.jsx";
import HomePage from "./components/homePage.jsx";
import AboutPage from "./components/about/aboutPage.jsx";
import AuthorPage from "./components/authors/authorPage.jsx";
import ManageAuthorPage from "./components/authors/manageAuthorPage.jsx";
import NotFoundPage from "./components/notFoundPage.jsx";

var routes = (
    <App>
        <Switch>
            <Route name="home" exact path="/" component={HomePage} />
            <Route name="authors" exact path="/authors" component={AuthorPage} />
            <Route name="addAuthor" exact path="/author" component={ManageAuthorPage} />
            <Route name="manageAuthor" path="/author/:id" component={ManageAuthorPage} />
            <Route name="about" exact path="/about" component={AboutPage} />
            <Route component={NotFoundPage} />
        </Switch>
    </App>
);

export default routes;

包含 BrowserRouter 的 main.js 文件

import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import routes from './routes.jsx';
import InitializeActions from './actions/initializeActions';

InitializeActions.initApp();

ReactDOM.render(<BrowserRouter>{routes}</BrowserRouter>, document.getElementById('app'));

以及包含导航栏的 header.jsx 文件

import React from 'react';
import {Link} from 'react-router-dom';

class Header extends React.Component {
    render() {
        return (
            <nav className="navbar navbar-default">
                <div className="container-fluid">
                    <Link to="/" className="navbar-brand">
                        <img src="../../images/pluralsight-logo.png"/>
                    </Link>
                    <ul className="nav navbar-nav">
                        <li><Link to="/">Home</Link></li>
                        <li><Link to="authors" ref={(comp) => { window.authorsTab=comp }}>Authors</Link></li>
                        <li><Link to="about">About</Link></li>
                    </ul>
                </div>
            </nav>
        );
    }
}

export default Header;

Gulpfile.js

"use strict";

var gulp = require('gulp');
var connect = require('gulp-connect'); //Runs a local dev server
var open = require('gulp-open'); //Opens a URL in a web browser
var browserify = require('browserify'); //Bundle JS
var reactify = require('reactify'); //Transforms react JSX to JS
var source = require('vinyl-source-stream'); //Use-conventional text streams with gulp
var concat = require('gulp-concat'); //concatnates files
var lint = require('gulp-eslint'); //lint our js files including jsx
var babelify = require("babelify");
var browserSync = require("browser-sync");

var config = {
  port: 9005,
  devBaseUrl: 'http://localhost',
  paths: {
    html: './src/*.html',
    js: './src/**/*.js*',
    images: './src/images/*',
    css: [
      'node_modules/bootstrap/dist/css/bootstrap.min.css',
      'node_modules/bootstrap/dist/css/bootstrap-theme.min.css',
      './src/dependencies/*.css',
      'node_modules/toastr/build/toastr.css'
    ],
    dist: './dist',
    mainJs: './src/main.jsx'
  }
}

//start a local dev server
gulp.task('connect', function() {
  connect.server({
    root: ['dist'],
    port: config.port,
    base: config.devBaseUrl,
    livereload: true
  });
});

//opens the URL in browser
gulp.task('open', ['connect'], function() {
  gulp.src('dist/index.html')
    .pipe(open({uri: config.devBaseUrl + ':' + config.port + '/'}));
});

//get all the html files from 'src', bundle them and place inside 'dist' and reload the server
gulp.task('html', function() {
  gulp.src(config.paths.html)
    .pipe(gulp.dest(config.paths.dist))
    .pipe(connect.reload());
});

gulp.task('js', function() {
  browserify(config.paths.mainJs)
    .transform(babelify, {presets: ["es2015", "react"]})
    .bundle()
    .on('error', console.error.bind(console))
    .pipe(source('bundle.js'))
    .pipe(gulp.dest(config.paths.dist + '/scripts'))
    .pipe(connect.reload());
});

gulp.task('css', function() {
  gulp.src(config.paths.css)
    .pipe(concat('bundle.css'))
    .pipe(gulp.dest(config.paths.dist + '/css'));
});

gulp.task('images', function() {
  gulp.src(config.paths.images)
    .pipe(gulp.dest(config.paths.dist + '/images'))
    .pipe(connect.reload());
});

gulp.task('lint', function() {
  return gulp.src(config.paths.js)
    .pipe(lint({configFile: 'eslint.config.json'}))
    .pipe(lint.format());
});

//watch any changes in html files
gulp.task('watch', function() {
  gulp.watch(config.paths.html, ['html']);
  gulp.watch(config.paths.js, ['js', 'lint']);  
  gulp.watch(config.paths.css, ['css']);  
});

//the default task
gulp.task('default', ['html', 'js', 'css', 'images', 'lint', 'open', 'watch']);

我尝试在多个来源上寻找解决方案,但似乎每个人都遵循与我类似的方法! 请看一看。在此先感谢:)

【问题讨论】:

    标签: reactjs react-router-v4


    【解决方案1】:

    使用 BrowserRouter 时,需要在 webpack 中添加 historApiFallback: true。

    将此添加到您的 webpack 配置中

    devServer: {
        historyApiFallback: true,
      },
    

    gulp 等价物是这样的:

    historyApiFallback = require('connect-history-api-fallback')
    
    
    //start a local dev server
    gulp.task('connect', function() {
      connect.server({
        root: ['dist'],
        port: config.port,
        base: config.devBaseUrl,
        livereload: true,
        middleware: [ historyApiFallback() ]
      });
    });
    

    查看this链接了解更多详情

    【讨论】:

    • 感谢 Shubham 的建议,但我没有使用 webpack。我正在使用 Gulp+Browserify 代替。 Browserify 是否有类似的方法,或者我应该切换到 webpack 吗?
    • 添加了等效的 gulp
    • 再次感谢 Shubham 的回答。我尝试将上述模块集成到我的 gulpfile.js 中,但无法将代码放置在正确的位置。能否请您看一下上述问题中更新的 gulpfile.js。
    • 更新了,可以看看
    • 非常感谢舒巴姆。最后这奏效了。您给出的解决方案略有变化(请参阅下面的答案)......继续努力!
    【解决方案2】:

    如果你使用的是 webpack-dev-server。设置:

    devServer{
      //...
      historyApiFallback: true
    }
    

    它将提供“index.html”来代替任何 404 响应...

    如果您已发布到服务器。请确保您的服务器配置使其重定向到主 html

    快递:

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

    一饮而尽:

    connect.server({
      root: ['dist'],
      port: config.port,
      base: config.devBaseUrl,
      livereload: true,
      fallback: 'index.html'
    });
    

    【讨论】:

    • 感谢LinJI的建议,但我没有使用webpack。我正在使用 Gulp+Browserify 代替。 Browserify 是否有类似的方法,或者我应该切换到 webpack 吗?
    • 你用什么技术做服务器?
    • 如果你根本不在服务器上运行,你必须使用HashRouter而不是BrowserRouter...
    • 我使用 node 作为我的开发服务器。但我发现问题不在于我的客户端路由(HashRouter 或 BrowserRouter)。 BrowserRouter 工作正常。但不处理服务器端路由(用于手动点击随机 URL)。所以我打算整合 Express。
    • 假设您有一个名为 index.html 的文件... localhost:xxxx 会将这个文件发送给客户端。但是,当您使用 BrowserRouter localhost:xxxx/a 时会响应 404 因为您没有在服务器上指定正确的路由。
    【解决方案3】:

    这对我有用:

      var historyApiFallback = require('connect-history-api-fallback');
    
      gulp.task('connect', function() {
        connect.server({
          root: ['dist'],
          port: config.port,
          base: config.devBaseUrl,
          livereload: true,
          middleware: function(connect, opt) {
            return [
              historyApiFallback({})
            ]
          }
        });
      });
    

    感谢@Shubham Khatri 和@LinJI 的所有帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-25
      • 2017-02-24
      • 1970-01-01
      • 2021-12-21
      相关资源
      最近更新 更多