URL-адреса React-маршрутизатора не работают при обновлении или записи вручную

407

Я использую React-router, и он отлично работает, когда я нажимаю кнопки ссылок, но когда я обновляю свою веб-страницу, он не загружает то, что я хочу.

Например, я вхожу в localhost/joblist, и все в порядке, потому что я приехал сюда, нажав ссылку. Но если я обновляю веб-страницу, я получаю: Не могу GET/joblist

По умолчанию Это не работает. Первоначально у меня был мой URL: localhost/#/и localhost/#/joblist, и они отлично работали. Но мне не нравится этот тип URL-адреса, поэтому я пытаюсь стереть это "#", я написал:

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

Эта проблема не возникает с localhost/, она всегда возвращает то, что я хочу.

EDIT: это одностраничное приложение, поэтому /joblist не нужно ничего спрашивать на каком-либо сервере.

EDIT2: весь мой маршрутизатор.

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);
});
  • 0
    если вы не используете htaccess для загрузки своей главной страницы туров и указания маршрутизатору использовать location.pathname, он не будет работать.
  • 0
    Как вы удалили этот символ # ? Спасибо!
Показать ещё 5 комментариев
Теги:
react-router
url
router

34 ответа

666
Лучший ответ

Рассматривая комментарии к принятому ответу и общий характер этого вопроса ("не работайте"), я подумал, что это может быть хорошим местом для некоторых общих объяснений по поводу проблем, которые здесь возникают.Таким образом, этот ответ предназначен как справочная информация/разработка конкретного варианта использования ОП.Пожалуйста, несите меня.

server- сторона на стороне клиента

Первое, что нужно понять, это то, что теперь есть 2 места, где URL интерпретируется, тогда как в "старые дни" было всего 1. Раньше, когда жизнь была простой, некоторый пользователь отправил запрос на http://example.com/about на сервер, который проверил часть пути URL-адреса, определил, что пользователь запрашивает о странице, а затем отправил обратно стр.

Благодаря маршрутизации на стороне клиента, что обеспечивает React-Router, все проще. Сначала у клиента еще нет загруженного кода JS. Поэтому самый первый запрос всегда будет на сервере. Затем он вернет страницу, содержащую необходимые теги сценария, для загрузки React и React Router и т.д. Только после загрузки этих сценариев начинается фаза 2. На этапе 2, когда пользователь нажимает ссылку "О нас", URL-адрес изменен локально только на http://example.com/about (что стало возможным благодаря API истории), но запрос на сервер отсутствует изготовлен. Вместо этого React Router делает это на стороне клиента, определяет, какое представление React отображает и отображает его. Предполагая, что вашей странице не нужно делать какие-либо звонки REST, это уже сделано. Вы перешли из Дома в О нас без запроса сервера.

Таким образом, в основном, когда вы нажимаете ссылку, выполняется несколько Javascript, которые манипулируют URL-адресом в адресной строке, не вызывая обновления страницы, что, в свою очередь, заставляет React Router выполнять переход страницы на стороне клиента.

Но теперь подумайте о том, что произойдет, если вы скопируете URL-адрес в адресной строке и отправьте по электронной почте другу. Ваш друг еще не загрузил ваш сайт. Другими словами, она все еще находится в фазе 1. На ней еще не работает Ract Router. Поэтому ее браузер сделает запрос на сервер http://example.com/about.

И тут твоя проблема начинается. До сих пор вы могли уйти, просто разместив статический HTML на веб-сайте своего сервера. Но это дало бы 404 ошибки для всех других URL-адресов при запросе с сервера. Те же самые URL-адреса отлично работают на стороне клиента, потому что React Router выполняет маршрутизацию для вас, но они не работают на стороне сервера, если вы не понимаете их на своем сервере.

Объединение server- и маршрутизации на стороне клиента

Если вы хотите, чтобы URL-адрес http://example.com/about работал как на server-, так и на стороне клиента, вам необходимо настроить маршруты для него как на server-, так и на стороне клиента. Имеет смысл?

И здесь начинается ваш выбор. Решения варьируются от обхода проблемы в целом, с помощью маршрута catch-all, который возвращает бутстрап HTML, в изоморфный подход полного доступа, где и сервер, и клиент используют один и тот же JS-код.

,

Обход проблемы в целом: история хеширования

С историей хеширования, а не с историей браузера, ваш URL-адрес для этой страницы будет выглядеть примерно так: http://example.com/#/about Часть после символа hash (#) не отправляется на сервер. Таким образом, сервер видит только http://example.com/ и отправляет индексную страницу, как ожидалось. React-Router забирает номер #/about и показывает правильную страницу.

Недостатки:

  • "уродливые" URL-адреса
  • server- боковой рендеринг невозможен при таком подходе. Что касается поисковой оптимизации (SEO), ваш сайт состоит из одной страницы, на которой практически нет контента.

,

Вместилище разнообразных предметов

При таком подходе вы используете историю браузеров, но просто настроили на сервере все, что отправляет /* в index.html, что дает вам ту же ситуацию, что и в истории хэширования. Однако у вас есть чистые URL-адреса, и вы можете улучшить эту схему позже, не отменяя всех своих избранных пользователей.

Недостатки:

  • Более сложная настройка
  • Еще ничего хорошего SEO

,

Гибридный

В гибридном подходе вы расширяетесь на сценарий catch-all, добавляя определенные сценарии для определенных маршрутов. Вы можете сделать несколько простых PHP-скриптов, чтобы вернуть наиболее важные страницы вашего сайта с включенным содержимым, поэтому робот Google может хотя бы увидеть, что на вашей странице.

Недостатки:

  • Еще сложнее настроить
  • Только хороший SEO для тех маршрутов, которые вы даете специальному лечению
  • Дублирующий код для рендеринга контента на сервере и клиенте

,

изоморфный

Что делать, если мы используем Node JS в качестве нашего сервера, чтобы мы могли запускать один и тот же JS-код на обоих концах? Теперь у нас есть все наши маршруты, определенные в одном конфигурационном файле-адаптере, и нам не нужно дублировать наш код рендеринга. Это "святой Грааль", так сказать. Сервер отправляет ту же самую разметку, что и в случае, если на клиенте произошел переход страницы. Это решение является оптимальным с точки зрения SEO.

Недостатки:

  • Сервер должен (иметь возможность) запускать JS. Я экспериментировал с Java icw Nashorn, но он не работает для меня. На практике это в основном означает, что вы должны использовать сервер Node JS.
  • Многие сложные экологические проблемы (использование window на стороне server- и т.д.)
  • Крутая кривая обучения

,

Что я должен использовать?

Выберите тот, с которым вы можете уйти. Лично я считаю, что все это достаточно просто, чтобы настроить, что это будет мой минимум. Эта настройка позволяет вам улучшать вещи с течением времени. Если вы уже используете Node JS в качестве серверной платформы, я бы определенно исследовал выполнение изоморфного приложения. Да, сначала это сложно, но как только вы получите это, на самом деле это очень изящное решение проблемы.

В принципе, для меня это будет решающим фактором. Если мой сервер работает на узле JS, я бы стал изоморфным, иначе я бы пошел на решение Catch-all и просто расширил его (гибридное решение) по мере продвижения времени и требований SEO.

Если вы хотите узнать больше об изоморфном (также называемом "универсальным") рендеринге с помощью React, есть несколько хороших руководств по этому вопросу:

Кроме того, чтобы вы начали, я рекомендую посмотреть некоторые стартовые наборы. Выберите тот, который соответствует вашим выборам для стека технологий (помните, React - это просто V в MVC, вам нужно больше материала для создания полного приложения). Начните с рассмотрения того, что опубликовано самим Facebook:

Или выберите одного из многих сообщества. Теперь есть хороший сайт, который пытается проиндексировать все из них:

Я начал с них:

В настоящее время я использую домашнюю версию универсального рендеринга, которая была вдохновлена двумя стартовыми наборами выше, но теперь они устарели.

Удачи вам в ваших поисках!

  • 2
    Великий пост Стейн! Вы бы порекомендовали пойти со стартовым набором для изоморфного приложения реакции? Если да, не могли бы вы привести пример, который вы бы предпочли?
  • 0
    @Chris Извините за задержку с ответом, я был в поездке. Я попробовал пару изоморфных стартовых наборов на самом деле. Я добавлю некоторую информацию об этом в пост.
Показать ещё 16 комментариев
79

Ответы здесь очень полезны, для меня работала настройка сервера Webpack на ожидаемые маршруты.

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

HistoryApiFallback - это то, что исправило эту проблему для меня. Теперь маршрутизация работает правильно, и я могу обновить страницу или ввести URL-адрес напрямую. Не нужно беспокоиться о работе на сервере node. Этот ответ, очевидно, работает только в том случае, если вы используете webpack.

ИЗМЕНИТЬ: см. мой ответ здесь для более подробной причины, почему это необходимо: https://stackoverflow.com/questions/36857147/react-router-2-0-browserhistory-doesnt-work-when-refreshing

  • 6
    Обратите внимание, что команда Webpack рекомендует не использовать dev-сервер в работе.
  • 4
    Для общих целей разработки это лучшее решение. historyApiFallback достаточно. Что касается всех других опций, он также может быть установлен из CLI с флагом --history-api-fallback .
Показать ещё 3 комментария
38

Для React Router V4 Пользователи:

Если вы попытаетесь решить эту проблему с помощью техники Hash History, упомянутой в других ответах, обратите внимание, что

<Router history={hashHistory} >

не работает в V4, вместо этого используйте HashRouter:

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

<HashRouter>
  <App/>
</HashRouter>

Ссылка: https://reacttraining.com/react-router/web/api/HashRouter

  • 1
    Это работает нормально для меня :) Спасибо.
  • 0
    работает на меня. но дополнительные "#" скучно ..
38

Вы можете изменить htaccess и вставить это:

RewriteBase /
RewriteRule ^index\.html$ - [L]
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]

Я использую react: "^15.3.2", react-router: "^3.0.0", history: "^4.3.0",

  • 3
    Это отлично работает! и самое простое, если вы не хотите реструктурировать свое приложение
  • 0
    Не забудьте RewriteEngine On в качестве первой строки
26

Маршрутизатор можно вызывать двумя разными способами, в зависимости от того, происходит ли навигация на клиенте или на сервере. Он настроен для работы на стороне клиента. Ключевым параметром является второй метод , расположение.

Когда вы используете компонент React Router Link, он блокирует навигацию браузера и вызывает переход для выполнения клиентской навигации. Вы используете HistoryLocation, поэтому он использует API истории HTML5 для завершения иллюзии навигации, моделируя новый URL-адрес в адресной строке. Если вы используете старые браузеры, это не сработает. Вам нужно будет использовать компонент HashLocation.

Когда вы нажмете обновление, вы обойдете весь код React и React Router. Сервер получает запрос для /joblist, и он должен что-то вернуть. На сервере вам необходимо передать путь, который был запрошен методу run, чтобы он отображал правильный вид. Вы можете использовать ту же карту маршрутов, но вам, вероятно, потребуется другой вызов Router.run. Как указывает Чарльз, вы можете использовать переписывание URL, чтобы справиться с этим. Другой вариант - использовать сервер node.js для обработки всех запросов и передать значение пути в качестве аргумента местоположения.

В экспресс, например, он может выглядеть следующим образом:

var app = express();

app.get('*', function (req, res) { // This wildcard method handles all requests

    Router.run(routes, req.path, function (Handler, state) {
        var element = React.createElement(Handler);
        var html = React.renderToString(element);
        res.render('main', { content: html });
    });
});

Обратите внимание, что путь запроса передается на run. Для этого вам понадобится серверный механизм просмотра, с помощью которого вы можете передать отображаемый HTML. Существует ряд других соображений, использующих renderToString и при запуске React на сервере. После того, как страница будет отображаться на сервере, когда ваше приложение загрузится на клиенте, оно снова отобразится, при необходимости обновив HTML-версию на стороне сервера.

  • 2
    извините, извините, не могли бы вы объяснить следующее утверждение: «когда вы нажимаете« обновить », вы обходите весь код React и React Router»? Почему это происходит?
  • 0
    React router обычно используется для обработки разных «путей» только внутри браузера. Есть два типичных способа сделать это: путь хеша старого стиля и более новый API истории. При обновлении браузера будет сделан запрос к серверу, который обойдёт ваш код реакции маршрутизатора на стороне клиента. Вам нужно будет обработать путь на сервере (но только если вы используете API истории). Для этого вы можете использовать реагирующий маршрутизатор, но вам нужно сделать что-то похожее на то, что я описал выше.
Показать ещё 8 комментариев
16

В head.html head добавьте следующее:

<base href="/">
<!-- This must come before the css and javascripts -->

Затем при работе с сервером webpack dev используйте эту команду.

webpack-dev-server --mode development --hot --inline --content-base=dist --history-api-fallback

--history-api-fallback - важная часть

  • 0
    Это сработало отлично! Есть какие-нибудь ссылки, чтобы узнать больше о том, как вы нашли / нашли это решение?
  • 1
    Извини брат. Обнаружил это с помощью проверенной методики проб и ошибок.
Показать ещё 4 комментария
14

У сервера Webpack Dev есть возможность включить это. Откройте package.json и добавьте --history-api-fallback. Эти решения работали для меня.

https://github.com/reactjs/react-router-tutorial/tree/master/lessons/10-clean-urls#configuring-your-server

  • 0
    это работает для меня тоже с реакции маршрутизатора v4
  • 0
    Это нормально с webpack-dev-server но как мне это исправить для производственной сборки?
11

Если вы принимаете приложение-ответ через AWS Static S3 Hosting & CloudFront

Эта проблема представила CloudFront, ответив сообщением об отказе в доступе 403, потому что он ожидал /some/other/path для существования в моей папке S3, но этот путь существует только внутри React routing с реактивным маршрутизатором.

Решение состояло в том, чтобы настроить правило Error Pages. Перейдите в настройки CloudFront и выберите свой дистрибутив. Затем перейдите на вкладку "Страницы ошибок". Нажмите "Создать пользовательский ответ об ошибке" и добавьте запись для 403, так как это код состояния ошибки, который мы получаем. Задайте путь страницы ответа в /index.html и код состояния до 200. Конечный результат удивляет меня своей простотой. Страница индексирования обслуживается, но URL-адрес сохраняется в браузере, поэтому, как только приложение реагирует на загрузку, он обнаруживает путь URL-адреса и переходит на нужный маршрут.

Ошибка страницы 403 Правило

11

Это может решить вашу проблему.

Я также столкнулся с той же проблемой в приложении ReactJS в режиме "Производство". Вот 2 решение проблемы.

1.Измените историю маршрутизации на "hashHistory" вместо имени браузера вместо

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

Теперь создайте приложение, используя команду

sudo npm run build

Затем поместите папку сборки в папку var/www/Now. Теперь приложение работает нормально с добавлением # тега в каждом URL-адресе. как

локальный/#/дома  локальный /#/ABOUTUS

Решение 2: Без тега #, использующего browserHistory,

Задайте свою историю = {browserHistory} в своем маршрутизаторе, теперь создайте ее, используя sudo npm run build.

Вам нужно создать файл "conf", чтобы решить 404 не найденную страницу, файл conf должен быть таким.

откройте свой тип терминала следующими командами

cd/etc/apache2/sites-available Ls nano sample.conf Добавьте в него содержимое ниже.

 <VirtualHost *:80>
    ServerAdmin [email protected]
    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>

Теперь вам нужно включить файл sample.conf, используя следующую команду

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

то он попросит вас перезагрузить сервер Apache, используя    sudo service apache2 перезагрузите или перезапустите

затем откройте папку localhost/build и добавьте файл .htaccess с содержимым ниже.

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

Теперь приложение работает нормально.

Примечание: измените 0.0.0.0 ip на локальный IP-адрес.

Если какие-либо сомнения относительно этого, не стесняйтесь поднимать комментарий.

Я надеюсь, что это будет полезно для других.

9

Я использовал приложение create-react-app для создания веб-сайта только сейчас и имел ту же самую проблему, представленную здесь. Я использую BrowserRouting из BrowserRouting react-router-dom. Я работаю на сервере Nginx, и для меня это решило добавить следующее: /etc/nginx/yourconfig.conf

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

Что соответствует добавлению следующего в .htaccess в случае, если вы используете Appache

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

Это также похоже на решение, предложенное самим Facebook, и его можно найти здесь

  • 1
    Это правильный ответ
  • 0
    Вау, такое простое решение для nginx; работает как шарм, как новый пользователь nginx. Просто скопируйте и вставьте. +1 за ссылку на официальную фб документацию. Путь
Показать ещё 1 комментарий
6

Попробуйте добавить файл ".htaccess" в общую папку с приведенным ниже кодом.

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

RewriteRule ^ /index.html [L]  
  • 0
    Большое спасибо. Вы спасли меня.
6

добавьте это в webpack.congif.js

devServer: {
      historyApiFallback: true
  }
6

Производственный стек: React, React Router v4, BrowswerRouter, Express, Nginx

1) User BrowserRouter для симпатичных URL-адресов

// app.js

import { BrowserRouter as Router } from 'react-router-dom'

const App = () {
  render() {
    return (
        <Router>
           // your routes here
        </Router>
    )
  }
}

2) Добавьте index.html ко всем неизвестным запросам с помощью /*

// server.js

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

3) пакетный webpack -p пакет с webpack -p

4) запустите nodemon server.js или node server.js

EDIT: вы можете позволить nginx обрабатывать это в блоке сервера и игнорировать шаг 2:

location / {
    try_files $uri /index.html;
}
  • 0
    получение пути неопределенного
  • 0
    @Goutham В верхней части файла server.js добавьте import path from 'path или const path = require('path')
Показать ещё 2 комментария
4

Если вы используете приложение Create React:

Там есть большая прогулка по этой проблеме с решениями для многих крупных платформ хостинга, которые вы можете найти ЗДЕСЬ на странице Создать приложение React. Например, я использую React Router v4 и Netlify для моего внешнего кода. Все, что нужно, это добавить 1 файл в мою общую папку ( "_redirects" ) и одну строку кода в этом файле:

/*  /index.html  200

Теперь мой сайт правильно отображает пути, такие как mysite.com/pricing, когда они введены в браузер или когда кто-то обращается к обновлению.

  • 1
    Благодаря тонну! Netlify это невероятно.
2

Если вы размещаете свое приложение-ответ в IIS, просто добавьте файл web.config, содержащий:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" path="/" responseMode="ExecuteURL" />
    </httpErrors>
  </system.webServer>
</configuration>

Это означает, что сервер IIS вернет основную страницу клиенту вместо ошибки 404 и не будет необходимости использовать историю хэша.

2

Эта тема немного устарела и решена, но я хотел бы предложить вам простое, ясное и лучшее решение. Он работает, если вы используете веб-сервер.

Каждый веб-сервер имеет возможность перенаправлять пользователя на страницу с ошибкой в ​​случае http 404. Для решения этой проблемы вам необходимо перенаправить пользователя на страницу индекса.

Если вы используете базовый сервер Java (tomcat или любой сервер приложений Java), решение может быть следующим:

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- WELCOME FILE LIST -->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <!-- ERROR PAGES DEFINITION -->
    <error-page>
        <error-code>404</error-code>
        <location>/index.jsp</location>
    </error-page>

</web-app>

Пример:

  • GET http://example.com/about
  • Веб-сервер выбрасывает http 404, потому что эта страница не существует на стороне сервера.
  • Конфигурация страницы ошибки сообщает серверу, который отправляет страницу index.jsp обратно пользователю
  • тогда JS выполнит оставшуюся часть задания со стороны clien, потому что URL-адрес на стороне клиента по-прежнему http://example.com/about.

То есть, больше не нужно магии:)

  • 0
    Это было потрясающе! Я использую сервер Wildfly 10.1 и сделал это обновление для моего файла web.xml, за исключением того, что для местоположения было установлено просто '/'. Это произошло потому, что в моем коде реагирования я использовал историю браузера следующим образом: const browserHistory = useRouterHistory(createHistory)({ basename: '/<appname>' });
  • 1
    Вы уверены, что это не влияет на SEO? Вы даете статус 404 тем страницам, которые действительно существуют. Пользователь может никогда этого не понять, но боты уделяют много внимания, на самом деле так много, что они не будут царапать вашу страницу.
2

Я пока не использую рендеринг на стороне сервера, но я сталкиваюсь с той же проблемой, что и OP, где ссылка, похоже, работает нормально большую часть времени, но не удалась, когда у меня был параметр. Я запишу свое решение здесь, чтобы узнать, помогает ли это кому-либо.

Мой главный jsx содержит следующее:

<Route onEnter={requireLogin} path="detail/:id" component={ModelDetail} />

Это отлично подходит для первой сопоставленной ссылки, но когда идентификатор: id изменяется в выражениях <Link>, вложенных в эту страницу подробностей модели, url изменяется в строке браузера, но содержимое страницы не изначально менялось, чтобы отразить связанный модель.

Проблема заключалась в том, что я использовал props.params.id для установки модели в componentDidMount. Компонент просто монтируется один раз, так что это означает, что первая модель является той, которая хранится на странице, а последующие ссылки меняют реквизиты, но оставляют страницу неизменной.

Установка модели в состоянии компонента как в componentDidMount, так и в componentWillReceiveProps (где она основана на следующих реквизитах) решает проблему, а содержимое страницы изменяется, чтобы отобразить желаемую модель.

  • 1
    Возможно, лучше использовать конструктор компонента (который также имеет доступ к props ) iso componentDidMount если вы когда-нибудь захотите попробовать рендеринг на стороне сервера. Потому что componentDidMount вызывается только в браузере. Его цель - делать вещи с DOM, такие как присоединение слушателей событий к body т. Д., Что вы не можете сделать в render .
2

Если у вас есть резерв на ваш index.html, убедитесь, что в вашем файле index.html есть следующее:

<script>
  System.config({ baseURL: '/' });
</script>

Это может отличаться от проекта к проекту.

  • 0
    Добавьте это к своей HTML- head : <base href = "/">
1

Если вы используете Express или какую-либо другую структуру в бэкэнд, вы можете добавить аналогичную конфигурацию, как показано ниже, и проверить общедоступный путь Webpack в конфигурации, она должна работать нормально даже при перезагрузке, если вы используете BrowserRouter

' expressApp.get('/*', (request, response) => {
    response.sendFile(path.join(__dirname, '../public/index.html'));
  });'
0

Я использую WebPack, у меня была такая же проблема Решение => В вашем файле server.js

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

app.use(express.static(path.resolve(__dirname, '../dist')));
  app.get('*', function (req, res) {
    res.sendFile(path.resolve(__dirname, '../dist/index.html'));
    // res.end();
  });

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

0

Полный маршрутизатор с примером (React Router v4):

Пример рабочего примера Проверьте проект ниже.

https://github.com/eh3rrera/react-router-4-example

После загрузки
1.) "npm install" в cmd для установки проекта
2.) "npm start", чтобы запустить приложение реакции

Примечание: вам нужно программное обеспечение Node js для запуска в ваших окнах. Mac OS имеет узел по умолчанию.

ура

0

Я нашел решение для моего SPA с реагирующим маршрутизатором (Apache). Просто добавьте в .htaccess

<IfModule mod_rewrite.c>

  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]

</IfModule>

источник: https://gist.github.com/alexsasharegan/173878f9d67055bfef63449fa7136042

0

Исправление ошибки "невозможно получить /URL" при обновлении или при непосредственном вызове URL.

Сконфигурируйте ваш webpack.config.js так, чтобы он ожидал, что по данной ссылке маршруты будут такими.

module.exports = {
  entry: './app/index.js',
  output: {
       path: path.join(__dirname, '/bundle'),
       filename: 'index_bundle.js',
       publicPath: '/'
    },
0

Мне нравится этот способ обработки. Попробуйте добавить: yourSPAPageRoute/* на стороне сервера, чтобы избавиться от этой проблемы.

Я пошел с этим подходом, потому что даже собственный API истории HTML5 не поддерживает правильное перенаправление при обновлении страницы (насколько я знаю).

Примечание. Выбранный ответ уже рассмотрел это, но я стараюсь быть более конкретным.

Экспресс-маршрут

Изображение 2684 Протестировано и просто хотел поделиться этим.

Надеюсь, поможет.

0

Комментарий -jimbotron помог мне, проблема была.htaccess

"Это ссылка, которая помогла решить мою проблему: https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#serving-apps-with-client -side-routing - jimbotron '

0

Если вы используете firebase, все, что вам нужно сделать, это убедиться, что у вас есть свойство rewrites в вашем файле firebase.json в корне вашего приложения (в разделе хостинга).

Например:

{ 
  "hosting": {
    "rewrites": [{
      "source":"**",
      "destination": "/index.html"
    }]    
  }
}

Надеюсь, это избавит кого-то еще от разочарования и впустую.

Счастливое кодирование...

Дальнейшее чтение по теме:

https://firebase.google.com/docs/hosting/full-config#rewrites

Firebase CLI: "Настроить как одностраничное приложение (переписать все URL-адреса в /index.html)"

  • 0
    Вы легенда
0

Для тех, кто использует IIS 10, это то, что вы должны сделать, чтобы сделать это правильно. Убедитесь, что вы используете browserHistory с этим. Что касается ссылки, я дам код для маршрутизации, но это не имеет значения, что важно для следующего шага после кода компонента ниже:

class App extends Component {
    render() {
        return (
            <Router history={browserHistory}>
                <div>
                    <Root>
                        <Switch>
                            <Route exact path={"/"} component={Home} />    
                            <Route path={"/home"} component={Home} />
                            <Route path={"/createnewproject"} component={CreateNewProject} />
                            <Route path={"/projects"} component={Projects} />
                            <Route path="*" component={NotFoundRoute} />
                        </Switch>
                    </Root>
                </div>
            </Router>
        )
    }
}
render (<App />, window.document.getElementById("app"));

Поскольку проблема заключается в том, что IIS получает запрос от клиентских браузеров, он будет интерпретировать URL-адрес так, как будто он запрашивает страницу, а затем возвращает страницу 404, так как нет доступной страницы. Выполните следующие действия:

  1. Открыть IIS
  2. Разверните сервер, затем откройте папку "Сайты"
  3. Нажмите веб-сайт/приложение
  4. Перейдите на страницу ошибок
  5. Откройте элемент статуса ошибки 404 в списке
  6. Вместо опции "Вставить содержимое из статического файла в ответ на ошибку" измените его на "Выполнить URL-адрес на этом сайте" и добавьте "/" значение косой черты в URL-адрес.

И теперь он будет работать нормально.

Изображение 2685 Изображение 2686

Я надеюсь, что это помогает. :-)

  • 0
    я люблю тебя чувак. нет гомо Спасибо тебе за это. :)
0

Его довольно простой, когда вы получили, не может получить ошибку 403 после обновления компонента dom. просто добавьте эту строку в конфигурацию вашего веб-пакета, 'historyApiFallback: true'. это спасет весь мой день.

0

Здесь есть много хороших ответов, и здесь не нужно писать больше ответов.

но, я предоставляю еще одну хорошую ссылку здесь

https://css-tricks.com/learning-react-router/#article-header-id-9

0

В случае, если кто-то ищет решение для React JS SPA с Laravel. Принятый ответ - лучшее объяснение того, почему такие проблемы происходят. Как уже объяснялось, вам необходимо настроить как клиентскую, так и серверную сторону. В свой шаблон клипа включите файл js в комплекте, обязательно используйте URL facade, как этот

<script src="{{ URL::to('js/user/spa.js') }}"></script>

В ваших маршрутах обязательно добавьте это в основную конечную точку, где находится шаблон клинка. Например,

Route::get('/setting-alerts', function () {
   return view('user.set-alerts');
});

Вышеприведенное является основной конечной точкой для шаблона клинка. Теперь добавьте необязательный маршрут,

Route::get('/setting-alerts/{spa?}', function () {
  return view('user.set-alerts');
});

Проблема заключается в том, что сначала загружается шаблон клинка, а затем реагирует маршрутизатор. Итак, когда вы загружаете '/setting-alerts', он загружает html и js. Но когда вы загружаете '/setting-alerts/about', он сначала загружается со стороны сервера. Поскольку на стороне сервера в этом месте ничего нет, он не возвращается. Когда у вас есть этот дополнительный маршрутизатор, он загружает ту же страницу и также загружает маршрутизатор, а затем реагирует загрузчик, решает, какой компонент будет отображаться. Надеюсь, это поможет.

  • 0
    Можно ли загрузить один точный URI на сервер, а затем сервер перенаправить на React? Например, когда я загружаю /user/{userID} , мне просто нужно вернуть универсальное /user HTML-представление, принести идентификатор и вызвать его, используя AJAX или axios. Возможно ли это сделать? они оптимизированы для SEO?
0

Решение для Preact с preact-router

Работает с обновлением и прямым доступом

Для тех, кто обнаруживает это через Google, вот демо истории preact-router + hash:

const { h, Component, render } = preact; /** @jsx h */
const { Router } = preactRouter;
const { createHashHistory } = History;
const App = () => (
    <div>
        <AddressBar />

        <Router history={createHashHistory()}>
            <div path="/">
                <p>
                    all paths in preact-router are still /normal/urls.
                    using hash history rewrites them to /#/hash/urls
                </p>
                Example: <a href="/page2">page 2</a>
            </div>
            <div path="/page2">
                <p>Page Two</p>
                <a href="/">back to home</a><br/>
            </div>
        </Router>
    </div>
);

https://jsfiddle.net/developit/gLyL6rbn/

0

У меня была такая же проблема, и это решение работало для нас..

Фон:

Мы размещаем несколько приложений на одном сервере. Когда мы обновим сервер, вы не поймете, где искать наш индекс в папке dist для этого конкретного приложения. Вышеупомянутая ссылка приведет вас к тому, что сработало для нас... Надеюсь, это поможет, поскольку мы потратили немало времени на разработку решения для наших нужд.

Мы используем:

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

Если вы размещаете в IIS; Добавление этого в мой webconfig решило мою проблему

    <httpErrors errorMode="Custom" defaultResponseMode="ExecuteURL">
        <remove statusCode="500" subStatusCode="100" />
        <remove statusCode="500" subStatusCode="-1" />
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" path="/" responseMode="ExecuteURL" />
        <error statusCode="500" prefixLanguageFilePath="" path="/error_500.asp" responseMode="ExecuteURL" />
        <error statusCode="500" subStatusCode="100" path="/error_500.asp" responseMode="ExecuteURL" />
    </httpErrors>

Вы можете сделать аналогичную конфигурацию для любого другого сервера

-9

Практическое обходное решение:

  • Дублировать и переименовывать исходный файл html в качестве joblist.html
  • Использовать joblist.html в качестве маршрута пути

Не требуется никаких изменений на стороне сервера.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню