React-router v4 - не может ПОЛУЧИТЬ *url*

Я начал использовать реактивный маршрутизатор v4. У меня есть простой <Router> в моем app.js с некоторыми навигационными ссылками (см. код ниже). Если я перехожу на localhost/vocabulary, роутер перенаправляет меня на нужную страницу. Однако, когда я нажимаю перезагрузить (F5) после (localhost/vocabulary), весь контент исчезает, а браузер сообщает Cannot GET /vocabulary. Как это возможно? Может ли кто-нибудь подсказать, как это решить (правильно перезагрузить страницу)?

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)

person exoslav    schedule 04.04.2017    source источник
comment
Возможный дубликат URL-адресов React-router не работает, когда обновление или запись вручную   -  person Chris    schedule 04.04.2017


Ответы (9)


Я предполагаю, что вы используете Webpack. Если это так, добавление нескольких вещей в конфигурацию вашего веб-пакета должно решить проблему. В частности, output.publicPath = '/' и devServer.historyApiFallback = true. Ниже приведен пример конфигурации веб-пакета, который использует оба ^ и устраняет проблему обновления для меня. Если вам интересно, «почему», это поможет.

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'
    })
  ]
};

Подробнее об этом я писал здесь — Исправление ошибки "cannot GET /URL" при обновлении с React Router (или как работают маршрутизаторы на стороне клиента)

person Tyler McGinnis    schedule 04.04.2017
comment
работал добавленным devServer: { historyApiFallback: true, }, - person SKLTFZ; 13.09.2017
comment
И не используйте HtmlWebpackPlugin с index.html в качестве шаблона, поскольку пакет не внедряется при обновлении маршрута. Вставьте скрипт bundle.js непосредственно как тег скрипта в index.html. - person peterorum; 20.09.2017
comment
У меня сработало просто добавление devServer { historyApiFallback: true } У меня уже было настроено publicPath: '/' - person Andre Evangelista; 04.12.2017
comment
Спасибо! Во многих источниках все говорят добавить historyApiFallback, но они никогда не упоминали о output.publicPath = '/'. Я не настроил свой publicPath, поэтому не мог решить свою проблему, пока не увидел ваш пост. - person Nezih; 16.02.2018
comment
Это сработало и для меня, добавив historyApiFallback: true к devServer. - person Cazineer; 20.03.2018
comment
У меня есть и historyApiFallback: true, и publicPath: /, но они не работают... также я использую экспресс-сервер... мне нужно настроить экспресс вместо веб-пакета? - person jsdev17; 25.03.2018
comment
+1 от меня и не забывайте перезапускать сервер (если у вас включена горячая загрузка) каждый раз, когда вы меняете webpack.config.js. - person BlondCode; 05.07.2018
comment
А что с производственной конфигурацией? - person Alex Green; 03.12.2018
comment
@SKLTFZ Какое решение, если я не использую веб-пакет? - person Bhatt Akshay; 01.03.2019
comment
Как это исправить без установки historyApiFallback: true? - person Huy; 15.12.2019
comment
Он работает на devServer. но после сборки не работает :( - person Jahirul Islam Mamun; 07.02.2020
comment
historyApiFallback мне достаточно - person k4st0r42; 28.04.2021
comment
Боже! Большое спасибо! - person metalheadcoder; 15.06.2021

Просто чтобы дополнить ответ Тайлера для тех, кто все еще борется с этим:

Добавление devServer.historyApiFallback: true в конфигурацию моего веб-пакета (без установки publicPath) исправило ошибки 404/Cannot-GET, которые я видел при обновлении/назад/вперед, но только для одного уровня вложенного маршрута. Другими словами, "/" и "/topics" начали работать нормально, но что-то еще (например, "/topics/независимо") по-прежнему вызывало ошибку 404 при обновлении/и т.д.

Только что наткнулся на принятый ответ здесь: Неожиданный токен ‹ ошибка в компоненте ответного маршрутизатора и это дало мне последний недостающий элемент. Добавление ведущего / к src скрипта пакета в моем index.html полностью решило проблему.

person Will Ashe    schedule 19.04.2017

Если ваше приложение размещено на статическом файловом сервере, вам нужно использовать вместо файла .

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

person jsina    schedule 10.09.2018
comment
Статья, на которую вы ссылались, была действительно полезной, потому что я использовал express.js. Этот код из статьи дал мне подсказку и решение для принятия другого URL-адреса, кроме /, поскольку он имеет звездочку в качестве аргумента функции get(). app.get('*', (req, res) =› { res.sendFile(path.resolve(__dirname, 'index.html')) }) - person Jerameel Resco; 29.06.2020

Это сработало для меня, просто нужно просто добавить devServer { historyApiFallback: true } в порядке, не нужно использовать publicPath: '/'

использование как:

  devServer: {
    historyApiFallback: true
  },
person kiss_von    schedule 18.09.2019

У меня была та же проблема, что исправило ее для меня, так это редактирование моего файла package.json и под scripts: {

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

в конце кода моего веб-пакета build я добавил --history-api-fallback, это также показалось самым простым решением ошибки Cannot GET /url

Примечание: в следующий раз, когда вы будете строить после добавления --history-api-fallback, вы увидите строку в выводе, которая выглядит следующим образом (с любым вашим индексным файлом):

Ошибка 404 вернется к /index.html.

person Jared    schedule 18.02.2018

Если вы используете Express (не Webpack), это сработало для меня.

app.get('/*', function(req, res) {
  res.sendFile(path.join(__dirname, 'path/to/your/index.html'), function(err) {
    if (err) {
      res.status(500).send(err)
    }
  })
})
person Marty McGee    schedule 24.12.2018
comment
Где вы должны написать этот код? В каком файле бэкенда? У меня есть app.js, index.js, а затем внутри контроллеров разные маршрутизаторы. Я использую экспресс.js. Также о пути index.html. О каком пути идет речь? У меня есть папка сборки внешнего интерфейса внутри моего корневого каталога бэкэнда. - person srishti77714; 26.03.2021

Если вы используете Webpack, проверьте свою конфигурацию в части конфигурации сервера для атрибута «contentBase». Вы можете установить на этом примере:

devServer: {
    ...
    contentBase: path.join(__dirname, '../')
    ...
}
person Alex    schedule 14.06.2018

Я также добился успеха, добавив ... historyApiFallback: true

devServer: {
    contentBase: path.join(__dirname, "public"),
    watchContentBase: true,
    publicPath: "/dist/",
    historyApiFallback: true
}
person SheldonO'Reilly    schedule 05.09.2018

Добавляя к принятому ответу, если вы используете HtmlWebpackPlugin и все еще получаете ошибки, дважды проверьте свойство filename. Если вы устанавливаете filename специально для производства, вам нужно будет добавить условие для установки зависимости filename от переменной WEBPACK_DEV_SERVER. См. пример ниже:

new HtmlWebpackPlugin({
   template: './src/index.html',
   filename: process.env.WEBPACK_DEV_SERVER ? 'index.html' : PROD_HTML_PATH,
})
person jhamPac    schedule 18.05.2021