React-Router v4 - kann * url * nicht abrufen


74

Ich fing an, React-Router v4 zu verwenden. Ich habe eine einfache <Router>in meiner app.js mit einigen Navigationslinks (siehe Code unten). Wenn ich zu navigiere localhost/vocabulary, leitet mich der Router auf die richtige Seite weiter. Wenn ich jedoch anschließend ( localhost/vocabulary) neu laden (F5) drücke , verschwinden alle Inhalte und der Browser meldet sich Cannot GET /vocabulary. Wie ist das möglich? Kann mir jemand einen Hinweis geben, wie ich das lösen kann (die Seite richtig laden)?

App.js:

import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
import { Switch, Redirect } from 'react-router'
import Login from './pages/Login'
import Vocabulary from './pages/Vocabulary'

const appContainer = document.getElementById('app')

ReactDOM.render(
  <Router>
    <div>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/vocabulary">Vocabulary</Link></li>
        </ul>
        <Switch>
          <Route exact path="/" component={Login} />
          <Route exact path="/vocabulary" component={Vocabulary} />
        </Switch>
    </div>
  </Router>,
appContainer)

Antworten:


215

Ich gehe davon aus, dass Sie Webpack verwenden. Wenn ja, sollte das Problem durch Hinzufügen einiger Dinge zu Ihrer Webpack-Konfiguration behoben werden. Insbesondere output.publicPath = '/'und devServer.historyApiFallback = true. Hier ist ein Beispiel für eine Webpack-Konfiguration, die beide von ^ verwendet und das Aktualisierungsproblem für mich behebt. Wenn Sie neugierig : „Warum“, dies wird dazu beitragen.

var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './app/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'index_bundle.js',
    publicPath: '/'
  },
  module: {
    rules: [
      { test: /\.(js)$/, use: 'babel-loader' },
      { test: /\.css$/, use: [ 'style-loader', 'css-loader' ]}
    ]
  },
  devServer: {
    historyApiFallback: true,
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'app/index.html'
    })
  ]
};

Ich habe hier mehr darüber geschrieben - Behebung des Fehlers "Kann nicht erhalten / URL" beim Aktualisieren mit React Router (oder wie clientseitige Router funktionieren)


17
bearbeitet von hinzugefügt devServer: {historyApiFallback: true,},
— SKLTFZ

Verwenden Sie HtmlWebpackPlugin nicht mit index.html als Vorlage, da das Bundle beim Aktualisieren einer Route nicht eingefügt wird. Fügen Sie das Skript bundle.js direkt als Skript-Tag in die Datei index.html ein.
— Peterorum

3
Es funktionierte für mich nur das Hinzufügen, das devServer { historyApiFallback: true } ich bereits publicPath: '/'konfiguriert hatte
— Andre Evangelista

Vielen Dank! In vielen Quellen sagen alle, dass sie historyApiFallback hinzufügen, aber sie hatten nie über output.publicPath = '/' gesprochen. Ich habe meinen publicPath nicht konfiguriert, sodass ich mein Problem erst lösen konnte, wenn ich Ihren Beitrag gesehen habe.
— Nezih

1
+1 von mir und vergessen Sie nicht, den Server jedes Mal neu zu starten (wenn Sie Hotload aktiviert haben), wenn Sie webpack.config.js ändern.
— BlondCode

15

Nur um Tylers Antwort für alle zu ergänzen, die immer noch damit zu kämpfen haben:

Durch Hinzufügen der devServer.historyApiFallback: truezu meiner Webpack-Konfiguration (ohne Einstellung publicPath) wurden die 404 / Cannot-GET-Fehler behoben, die beim Aktualisieren / Zurück / Vorwärts angezeigt wurden , jedoch nur für eine einzelne Ebene verschachtelter Routen. Mit anderen Worten, "/" und "/ topic" funktionierten einwandfrei, aber alles darüber hinaus (z. B. "/ topic / Whatever") warf immer noch einen 404 auf refresh / etc.

Ich bin gerade auf die akzeptierte Antwort hier gestoßen : Unerwartetes Token <Fehler in der React Router-Komponente und es war das letzte fehlende Teil für mich. Das Hinzufügen des führenden /zum Bundle-Skript src in my index.htmlhat das Problem vollständig gelöst.


5

Wenn Ihre Anwendung auf einem statischen Dateiserver gehostet wird, müssen Sie a anstelle von a verwenden.

import { HashRouter } from 'react-router-dom'

ReactDOM.render((
  <HashRouter>
    <App />
  </HashRouter>
), holder)

https://github.com/ReactTraining/react-router/blob/v4.1.1/FAQ.md#why-doesnt-my-application-render-after-refreshing


1
Der Artikel, auf den Sie verwiesen haben, war sehr hilfreich, da ich express.js verwendet habe. Dieser Code aus dem Artikel gab mir den Hinweis und die Lösung, neben dem "/" eine andere URL zu akzeptieren, da er ein Sternchen als Argument für die Funktion get () enthält. app.get ('*', (req, res) => {res.sendFile (path.resolve (__ dirname, 'index.html'))})
— Jerameel Resco

5

Es hat bei mir funktioniert, ich brauche nur das Hinzufügen devServer { historyApiFallback: true }ist in Ordnung, brauche keine VerwendungpublicPath: '/'

Verwendung wie:

  devServer: {
    historyApiFallback: true
  },

3

Ich hatte das gleiche Problem. Was es für mich behoben hat, war das Bearbeiten meiner package.jsonDatei und darunterscripts: {

"build": "webpack -d && copy src\\index.html dist\\index.html /y && webpack-dev-server --content-base src --inline --port 3000"

Am Ende meines Webpack- buildCodes fügte ich hinzu, dass --history-api-fallback dies auch die einfachste Lösung für den Cannot GET /urlFehler zu sein schien

Hinweis: Wenn --history-api-fallbackSie das nächste Mal nach dem Hinzufügen erstellen, werden Sie eine Zeile in der Ausgabe bemerken, die so aussieht (mit welcher Indexdatei auch immer):

404s greifen auf /index.html zurück


2

Wenn Sie Express (nicht Webpack) verwenden, hat dies bei mir funktioniert.

app.get('/*', function(req, res) {
  res.sendFile(path.join(__dirname, 'path/to/your/index.html'), function(err) {
    if (err) {
      res.status(500).send(err)
    }
  })
})

1

Wenn Sie Webpack verwenden, überprüfen Sie Ihre Konfiguration in einem Teil der Serverkonfiguration auf das Attribut "contentBase". Sie können anhand dieses Beispiels Folgendes festlegen:

devServer: {
    ...
    contentBase: path.join(__dirname, '../')
    ...
}

1

Ich hatte auch Erfolg damit, indem ich ... historyApiFallback: true

devServer: {
    contentBase: path.join(__dirname, "public"),
    watchContentBase: true,
    publicPath: "/dist/",
    historyApiFallback: true
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.